summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2007-08-10 16:14:01 -0400
committerAli Saidi <saidi@eecs.umich.edu>2007-08-10 16:14:01 -0400
commit06a9f58c68b621f082d39299bdb01f59ef68ef0e (patch)
tree51d9b7982e124d9acccdd8e8fdd8cecf96c0f83f /src
parent5c38668ed68fae7ed18571571d7855b541c4b039 (diff)
downloadgem5-06a9f58c68b621f082d39299bdb01f59ef68ef0e.tar.xz
DMA: Add IOCache and fix bus bridge to optionally only send requests one
way so a cache can handle partial block requests for i/o devices. --HG-- extra : convert_revision : a68b5ae826731bc87ed93eb7ef326a2393053964
Diffstat (limited to 'src')
-rw-r--r--src/base/range_ops.hh55
-rw-r--r--src/dev/io_device.hh3
-rw-r--r--src/mem/Bridge.py6
-rw-r--r--src/mem/bridge.cc33
-rw-r--r--src/mem/bridge.hh6
-rw-r--r--src/mem/bus.cc5
-rw-r--r--src/mem/bus.hh2
-rw-r--r--src/mem/cache/BaseCache.py4
-rw-r--r--src/mem/cache/base_cache.cc5
-rw-r--r--src/mem/cache/base_cache.hh16
-rw-r--r--src/mem/cache/cache.hh6
-rw-r--r--src/mem/cache/cache_builder.cc3
-rw-r--r--src/mem/cache/cache_impl.hh23
13 files changed, 120 insertions, 47 deletions
diff --git a/src/base/range_ops.hh b/src/base/range_ops.hh
new file mode 100644
index 000000000..f2b11b649
--- /dev/null
+++ b/src/base/range_ops.hh
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * 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: Ali Saidi
+ */
+
+#ifndef __BASE_RANGE_OPS_HH__
+#define __BASE_RANGE_OPS_HH__
+#include <list>
+#include <vector>
+
+#include "base/range.hh"
+
+template <class T>
+inline void
+FilterRangeList(std::vector<Range<T> > filter_list, std::list<Range<T> >
+ &range_list) {
+ typename std::list<Range<T> >::iterator i;
+ for (int x = 0; x < filter_list.size(); x++) {
+ for (i = range_list.begin(); i != range_list.end(); ) {
+ // Is the range within one of our filter ranges?
+ if (filter_list[x] == i->start || filter_list[x] == i->end)
+ range_list.erase(i++);
+ else
+ i++;
+ }
+ }
+}
+
+#endif //__BASE_RANGE_OPS_HH__
+
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index e65400ca2..876166adb 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -266,8 +266,7 @@ class DmaDevice : public PioDevice
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
{
- dmaPort->dmaAction(MemCmd::WriteInvalidateReq,
- addr, size, event, data);
+ dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data);
}
void dmaRead(Addr addr, int size, Event *event, uint8_t *data)
diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py
index 8377221cd..b48e1684d 100644
--- a/src/mem/Bridge.py
+++ b/src/mem/Bridge.py
@@ -40,5 +40,7 @@ class Bridge(MemObject):
delay = Param.Latency('0ns', "The latency of this bridge")
nack_delay = Param.Latency('0ns', "The latency of this bridge")
write_ack = Param.Bool(False, "Should this bridge ack writes")
- fix_partial_write_a = Param.Bool(False, "Should this bridge fixup partial block writes")
- fix_partial_write_b = Param.Bool(False, "Should this bridge fixup partial block writes")
+ filter_ranges_a = VectorParam.AddrRange([],
+ "What addresses shouldn't be passed through the side of the bridge")
+ filter_ranges_b = VectorParam.AddrRange([],
+ "What addresses shouldn't be passed through the side of the bridge")
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 6cfa5a2ac..c502c5130 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -37,6 +37,7 @@
#include <algorithm>
+#include "base/range_ops.hh"
#include "base/trace.hh"
#include "mem/bridge.hh"
#include "params/Bridge.hh"
@@ -44,9 +45,10 @@
Bridge::BridgePort::BridgePort(const std::string &_name,
Bridge *_bridge, BridgePort *_otherPort,
int _delay, int _nack_delay, int _req_limit,
- int _resp_limit, bool fix_partial_write)
+ int _resp_limit,
+ std::vector<Range<Addr> > filter_ranges)
: Port(_name), bridge(_bridge), otherPort(_otherPort),
- delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write),
+ delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges),
outstandingResponses(0), queuedRequests(0), inRetry(false),
reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this)
{
@@ -55,9 +57,9 @@ Bridge::BridgePort::BridgePort(const std::string &_name,
Bridge::Bridge(Params *p)
: MemObject(p->name),
portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay,
- p->req_size_a, p->resp_size_a, p->fix_partial_write_a),
+ p->req_size_a, p->resp_size_a, p->filter_ranges_a),
portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay,
- p->req_size_b, p->resp_size_b, p->fix_partial_write_b),
+ p->req_size_b, p->resp_size_b, p->filter_ranges_b),
ackWrites(p->write_ack), _params(p)
{
if (ackWrites)
@@ -243,17 +245,6 @@ Bridge::BridgePort::trySend()
PacketPtr pkt = buf->pkt;
- // Ugly! @todo When multilevel coherence works this will be removed
- if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
- !pkt->wasNacked()) {
- PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
- Packet::Broadcast);
- funcPkt->dataStatic(pkt->getPtr<uint8_t>());
- sendFunctional(funcPkt);
- pkt->cmd = MemCmd::WriteReq;
- delete funcPkt;
- }
-
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
buf->origSrc, pkt->getDest(), pkt->getAddr());
@@ -313,17 +304,6 @@ Bridge::BridgePort::recvRetry()
Tick
Bridge::BridgePort::recvAtomic(PacketPtr pkt)
{
- // fix partial atomic writes... similar to the timing code that does the
- // same... will be removed once our code gets this right
- if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) {
-
- PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
- Packet::Broadcast);
- funcPkt->dataStatic(pkt->getPtr<uint8_t>());
- otherPort->sendFunctional(funcPkt);
- delete funcPkt;
- pkt->cmd = MemCmd::WriteReq;
- }
return delay + otherPort->sendAtomic(pkt);
}
@@ -355,6 +335,7 @@ Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
bool &snoop)
{
otherPort->getPeerAddressRanges(resp, snoop);
+ FilterRangeList(filterRanges, resp);
// we don't allow snooping across bridges
snoop = false;
}
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index d3bbf2ddf..82001948e 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -70,7 +70,8 @@ class Bridge : public MemObject
/** Min delay to respond to a nack. */
Tick nackDelay;
- bool fixPartialWrite;
+ /** Pass ranges from one side of the bridge to the other? */
+ std::vector<Range<Addr> > filterRanges;
class PacketBuffer : public Packet::SenderState {
@@ -156,7 +157,8 @@ class Bridge : public MemObject
/** Constructor for the BusPort.*/
BridgePort(const std::string &_name, Bridge *_bridge,
BridgePort *_otherPort, int _delay, int _nack_delay,
- int _req_limit, int _resp_limit, bool fix_partial_write);
+ int _req_limit, int _resp_limit,
+ std::vector<Range<Addr> > filter_ranges);
protected:
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index eba96b4d2..42c4431bb 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -457,6 +457,10 @@ Bus::recvStatusChange(Port::Status status, int id)
bool snoops;
AddrRangeIter iter;
+ if (inRecvStatusChange.count(id))
+ return;
+ inRecvStatusChange.insert(id);
+
assert(status == Port::RangeChange &&
"The other statuses need to be implemented.");
@@ -524,6 +528,7 @@ Bus::recvStatusChange(Port::Status status, int id)
if (id != defaultId && defaultPort)
defaultPort->sendStatusChange(Port::RangeChange);
+ inRecvStatusChange.erase(id);
}
void
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 83a4f6a55..0c594c463 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -38,6 +38,7 @@
#define __MEM_BUS_HH__
#include <string>
+#include <set>
#include <list>
#include <inttypes.h>
@@ -253,6 +254,7 @@ class Bus : public MemObject
BusFreeEvent busIdle;
bool inRetry;
+ std::set<int> inRecvStatusChange;
/** max number of bus ids we've handed out so far */
short maxId;
diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py
index 2bf44cdf9..f6d42b1ef 100644
--- a/src/mem/cache/BaseCache.py
+++ b/src/mem/cache/BaseCache.py
@@ -81,4 +81,8 @@ class BaseCache(MemObject):
"Only prefetch on data not on instruction accesses")
cpu_side = Port("Port on side closer to CPU")
mem_side = Port("Port on side closer to MEM")
+ cpu_side_filter_ranges = VectorParam.AddrRange([],
+ "What addresses shouldn't be passed through the side of the bridge")
+ mem_side_filter_ranges = VectorParam.AddrRange([],
+ "What addresses shouldn't be passed through the side of the bridge")
addr_range = VectorParam.AddrRange(AllMemory, "The address range in bytes")
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index b44468486..0c8b02cb3 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -40,9 +40,10 @@
using namespace std;
-BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache)
+BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
+ std::vector<Range<Addr> > filter_ranges)
: SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL),
- blocked(false), mustSendRetry(false)
+ blocked(false), mustSendRetry(false), filterRanges(filter_ranges)
{
}
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 719ab0245..6a4eec43e 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -98,7 +98,8 @@ class BaseCache : public MemObject
BaseCache *cache;
protected:
- CachePort(const std::string &_name, BaseCache *_cache);
+ CachePort(const std::string &_name, BaseCache *_cache,
+ std::vector<Range<Addr> > filter_ranges);
virtual void recvStatusChange(Status status);
@@ -124,6 +125,9 @@ class BaseCache : public MemObject
bool mustSendRetry;
+ /** filter ranges */
+ std::vector<Range<Addr> > filterRanges;
+
void requestBus(RequestCause cause, Tick time)
{
DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause);
@@ -367,15 +371,21 @@ class BaseCache : public MemObject
*/
Counter maxMisses;
+ std::vector<Range<Addr> > cpuSideFilterRanges;
+ std::vector<Range<Addr> > memSideFilterRanges;
/**
* Construct an instance of this parameter class.
*/
Params(int _hitLatency, int _blkSize,
int _numMSHRs, int _numTargets, int _numWriteBuffers,
- Counter _maxMisses)
+ Counter _maxMisses,
+ std::vector<Range<Addr> > cpu_side_filter_ranges,
+ std::vector<Range<Addr> > mem_side_filter_ranges)
: hitLatency(_hitLatency), blkSize(_blkSize),
numMSHRs(_numMSHRs), numTargets(_numTargets),
- numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses)
+ numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses),
+ cpuSideFilterRanges(cpu_side_filter_ranges),
+ memSideFilterRanges(mem_side_filter_ranges)
{
}
};
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 57028a05e..821fa9702 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -72,7 +72,8 @@ class Cache : public BaseCache
{
public:
CpuSidePort(const std::string &_name,
- Cache<TagStore> *_cache);
+ Cache<TagStore> *_cache,
+ std::vector<Range<Addr> > filterRanges);
// BaseCache::CachePort just has a BaseCache *; this function
// lets us get back the type info we lost when we stored the
@@ -95,7 +96,8 @@ class Cache : public BaseCache
{
public:
MemSidePort(const std::string &_name,
- Cache<TagStore> *_cache);
+ Cache<TagStore> *_cache,
+ std::vector<Range<Addr> > filterRanges);
// BaseCache::CachePort just has a BaseCache *; this function
// lets us get back the type info we lost when we stored the
diff --git a/src/mem/cache/cache_builder.cc b/src/mem/cache/cache_builder.cc
index 4c9592a1b..0f8b52af2 100644
--- a/src/mem/cache/cache_builder.cc
+++ b/src/mem/cache/cache_builder.cc
@@ -241,7 +241,8 @@ BaseCacheParams::create()
// Build BaseCache param object
BaseCache::Params base_params(latency, block_size,
mshrs, tgts_per_mshr, write_buffers,
- max_miss_count);
+ max_miss_count, cpu_side_filter_ranges,
+ mem_side_filter_ranges);
//Warnings about prefetcher policy
if (prefetch_policy == Enums::none) {
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index d144266ed..402e34db2 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -39,6 +39,7 @@
#include "sim/host.hh"
#include "base/misc.hh"
+#include "base/range_ops.hh"
#include "mem/cache/cache.hh"
#include "mem/cache/cache_blk.hh"
@@ -61,8 +62,10 @@ Cache<TagStore>::Cache(const std::string &_name,
tempBlock = new BlkType();
tempBlock->data = new uint8_t[blkSize];
- cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
- memSidePort = new MemSidePort(_name + "-mem_side_port", this);
+ cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this,
+ params.baseParams.cpuSideFilterRanges);
+ memSidePort = new MemSidePort(_name + "-mem_side_port", this,
+ params.baseParams.memSideFilterRanges);
cpuSidePort->setOtherPort(memSidePort);
memSidePort->setOtherPort(cpuSidePort);
@@ -88,7 +91,8 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx)
} else if (if_name == "mem_side") {
return memSidePort;
} else if (if_name == "functional") {
- return new CpuSidePort(name() + "-cpu_side_funcport", this);
+ return new CpuSidePort(name() + "-cpu_side_funcport", this,
+ std::vector<Range<Addr> >());
} else {
panic("Port name %s unrecognized\n", if_name);
}
@@ -1221,6 +1225,7 @@ getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
// CPU side port doesn't snoop; it's a target only.
bool dummy;
otherPort->getPeerAddressRanges(resp, dummy);
+ FilterRangeList(filterRanges, resp);
snoop = false;
}
@@ -1262,8 +1267,9 @@ Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
template<class TagStore>
Cache<TagStore>::
CpuSidePort::CpuSidePort(const std::string &_name,
- Cache<TagStore> *_cache)
- : BaseCache::CachePort(_name, _cache)
+ Cache<TagStore> *_cache, std::vector<Range<Addr> >
+ filterRanges)
+ : BaseCache::CachePort(_name, _cache, filterRanges)
{
}
@@ -1279,6 +1285,8 @@ Cache<TagStore>::MemSidePort::
getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
{
otherPort->getPeerAddressRanges(resp, snoop);
+ FilterRangeList(filterRanges, resp);
+
// Memory-side port always snoops, so unconditionally set flag for
// caller.
snoop = true;
@@ -1416,8 +1424,9 @@ Cache<TagStore>::MemSidePort::processSendEvent()
template<class TagStore>
Cache<TagStore>::
-MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache)
- : BaseCache::CachePort(_name, _cache)
+MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache,
+ std::vector<Range<Addr> > filterRanges)
+ : BaseCache::CachePort(_name, _cache, filterRanges)
{
// override default send event from SimpleTimingPort
delete sendEvent;