summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-05-31 20:45:04 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-05-31 20:45:04 +0000
commitc432588981c2903fda4b00bf03ada3c2c04063f7 (patch)
tree6230df1fe2f4032ef76973f8debcccfed6830285 /src/mem
parent62fde97bb2e40002e59d0185db419f6f72643a6f (diff)
parent6b6de8aaae86ea8b0f416a175c547fc67bea804a (diff)
downloadgem5-c432588981c2903fda4b00bf03ada3c2c04063f7.tar.xz
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 src/cpu/simple/base.cc: Hand merge --HG-- extra : convert_revision : a2902ef9d917d22ffb9c7dfa2fd444694a65240d
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/Bridge.py44
-rw-r--r--src/mem/Bus.py49
-rw-r--r--src/mem/MemObject.py34
-rw-r--r--src/mem/PhysicalMemory.py57
-rw-r--r--src/mem/SConscript5
-rw-r--r--src/mem/cache/BaseCache.py91
-rw-r--r--src/mem/cache/SConscript2
-rw-r--r--src/mem/cache/coherence/CoherenceProtocol.py8
-rw-r--r--src/mem/cache/coherence/SConscript2
-rw-r--r--src/mem/cache/tags/Repl.py11
-rw-r--r--src/mem/cache/tags/SConscript1
-rw-r--r--src/mem/packet.cc11
-rw-r--r--src/mem/packet.hh16
-rw-r--r--src/mem/physical.cc15
-rw-r--r--src/mem/tport.cc142
-rw-r--r--src/mem/tport.hh66
16 files changed, 442 insertions, 112 deletions
diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py
new file mode 100644
index 000000000..8377221cd
--- /dev/null
+++ b/src/mem/Bridge.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2006-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
+
+from m5.params import *
+from MemObject import MemObject
+
+class Bridge(MemObject):
+ type = 'Bridge'
+ side_a = Port('Side A port')
+ side_b = Port('Side B port')
+ req_size_a = Param.Int(16, "The number of requests to buffer")
+ req_size_b = Param.Int(16, "The number of requests to buffer")
+ resp_size_a = Param.Int(16, "The number of requests to buffer")
+ resp_size_b = Param.Int(16, "The number of requests to buffer")
+ 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")
diff --git a/src/mem/Bus.py b/src/mem/Bus.py
new file mode 100644
index 000000000..247a1fe31
--- /dev/null
+++ b/src/mem/Bus.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2005-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: Nathan Binkert
+
+from m5 import build_env
+from m5.params import *
+from m5.proxy import *
+from MemObject import MemObject
+
+if build_env['FULL_SYSTEM']:
+ from Device import BadAddr
+
+class Bus(MemObject):
+ type = 'Bus'
+ port = VectorPort("vector port for connecting devices")
+ bus_id = Param.Int(0, "blah")
+ clock = Param.Clock("1GHz", "bus clock speed")
+ width = Param.Int(64, "bus width (bytes)")
+ responder_set = Param.Bool(False, "Did the user specify a default responder.")
+ block_size = Param.Int(64, "The default block size if one isn't set by a device attached to the bus.")
+ if build_env['FULL_SYSTEM']:
+ responder = BadAddr(pio_addr=0x0, pio_latency="1ps")
+ default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.")
+ else:
+ default = Port("Default port for requests that aren't handled by a device.")
diff --git a/src/mem/MemObject.py b/src/mem/MemObject.py
new file mode 100644
index 000000000..269cf4403
--- /dev/null
+++ b/src/mem/MemObject.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2006-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: Ron Dreslinski
+
+from m5.SimObject import SimObject
+from m5.SimObject import SimObject
+
+class MemObject(SimObject):
+ type = 'MemObject'
+ abstract = True
diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py
new file mode 100644
index 000000000..2ef3df7c1
--- /dev/null
+++ b/src/mem/PhysicalMemory.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2005-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: Nathan Binkert
+
+from m5.params import *
+from m5.proxy import *
+from MemObject import *
+
+class PhysicalMemory(MemObject):
+ type = 'PhysicalMemory'
+ port = VectorPort("the access port")
+ range = Param.AddrRange(AddrRange('128MB'), "Device Address")
+ file = Param.String('', "memory mapped file")
+ latency = Param.Latency('1t', "latency of an access")
+ zero = Param.Bool(False, "zero initialize memory")
+
+class DRAMMemory(PhysicalMemory):
+ type = 'DRAMMemory'
+ # Many of these should be observed from the configuration
+ cpu_ratio = Param.Int(5,"ratio between CPU speed and memory bus speed")
+ mem_type = Param.String("SDRAM", "Type of DRAM (DRDRAM, SDRAM)")
+ mem_actpolicy = Param.String("open", "Open/Close policy")
+ memctrladdr_type = Param.String("interleaved", "Mapping interleaved or direct")
+ bus_width = Param.Int(16, "")
+ act_lat = Param.Int(2, "RAS to CAS delay")
+ cas_lat = Param.Int(1, "CAS delay")
+ war_lat = Param.Int(2, "write after read delay")
+ pre_lat = Param.Int(2, "precharge delay")
+ dpl_lat = Param.Int(2, "data in to precharge delay")
+ trc_lat = Param.Int(6, "row cycle delay")
+ num_banks = Param.Int(4, "Number of Banks")
+ num_cpus = Param.Int(4, "Number of CPUs connected to DRAM")
+
diff --git a/src/mem/SConscript b/src/mem/SConscript
index 61fb766d6..bbb1e96fe 100644
--- a/src/mem/SConscript
+++ b/src/mem/SConscript
@@ -30,6 +30,11 @@
Import('*')
+SimObject('Bridge.py')
+SimObject('Bus.py')
+SimObject('PhysicalMemory.py')
+SimObject('MemObject.py')
+
Source('bridge.cc')
Source('bus.cc')
Source('dram.cc')
diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py
new file mode 100644
index 000000000..4b98f6b30
--- /dev/null
+++ b/src/mem/cache/BaseCache.py
@@ -0,0 +1,91 @@
+# Copyright (c) 2005-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: Nathan Binkert
+
+from m5.params import *
+from MemObject import MemObject
+
+class Prefetch(Enum): vals = ['none', 'tagged', 'stride', 'ghb']
+
+class BaseCache(MemObject):
+ type = 'BaseCache'
+ adaptive_compression = Param.Bool(False,
+ "Use an adaptive compression scheme")
+ assoc = Param.Int("associativity")
+ block_size = Param.Int("block size in bytes")
+ latency = Param.Latency("Latency")
+ compressed_bus = Param.Bool(False,
+ "This cache connects to a compressed memory")
+ compression_latency = Param.Latency('0ns',
+ "Latency in cycles of compression algorithm")
+ hash_delay = Param.Int(1, "time in cycles of hash access")
+ lifo = Param.Bool(False,
+ "whether this NIC partition should use LIFO repl. policy")
+ max_miss_count = Param.Counter(0,
+ "number of misses to handle before calling exit")
+ mshrs = Param.Int("number of MSHRs (max outstanding requests)")
+ prioritizeRequests = Param.Bool(False,
+ "always service demand misses first")
+ protocol = Param.CoherenceProtocol(NULL, "coherence protocol to use")
+ repl = Param.Repl(NULL, "replacement policy")
+ size = Param.MemorySize("capacity in bytes")
+ split = Param.Bool(False, "whether or not this cache is split")
+ split_size = Param.Int(0,
+ "How many ways of the cache belong to CPU/LRU partition")
+ store_compressed = Param.Bool(False,
+ "Store compressed data in the cache")
+ subblock_size = Param.Int(0,
+ "Size of subblock in IIC used for compression")
+ tgts_per_mshr = Param.Int("max number of accesses per MSHR")
+ trace_addr = Param.Addr(0, "address to trace")
+ two_queue = Param.Bool(False,
+ "whether the lifo should have two queue replacement")
+ write_buffers = Param.Int(8, "number of write buffers")
+ prefetch_miss = Param.Bool(False,
+ "wheter you are using the hardware prefetcher from Miss stream")
+ prefetch_access = Param.Bool(False,
+ "wheter you are using the hardware prefetcher from Access stream")
+ prefetcher_size = Param.Int(100,
+ "Number of entries in the harware prefetch queue")
+ prefetch_past_page = Param.Bool(False,
+ "Allow prefetches to cross virtual page boundaries")
+ prefetch_serial_squash = Param.Bool(False,
+ "Squash prefetches with a later time on a subsequent miss")
+ prefetch_degree = Param.Int(1,
+ "Degree of the prefetch depth")
+ prefetch_latency = Param.Tick(10,
+ "Latency of the prefetcher")
+ prefetch_policy = Param.Prefetch('none',
+ "Type of prefetcher to use")
+ prefetch_cache_check_push = Param.Bool(True,
+ "Check if in cash on push or pop of prefetch queue")
+ prefetch_use_cpu_id = Param.Bool(True,
+ "Use the CPU ID to seperate calculations of prefetches")
+ prefetch_data_accesses_only = Param.Bool(False,
+ "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")
diff --git a/src/mem/cache/SConscript b/src/mem/cache/SConscript
index 7150719ad..546e037bd 100644
--- a/src/mem/cache/SConscript
+++ b/src/mem/cache/SConscript
@@ -30,6 +30,8 @@
Import('*')
+SimObject('BaseCache.py')
+
Source('base_cache.cc')
Source('cache.cc')
Source('cache_builder.cc')
diff --git a/src/mem/cache/coherence/CoherenceProtocol.py b/src/mem/cache/coherence/CoherenceProtocol.py
new file mode 100644
index 000000000..82adb6862
--- /dev/null
+++ b/src/mem/cache/coherence/CoherenceProtocol.py
@@ -0,0 +1,8 @@
+from m5.SimObject import SimObject
+from m5.params import *
+class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi']
+
+class CoherenceProtocol(SimObject):
+ type = 'CoherenceProtocol'
+ do_upgrades = Param.Bool(True, "use upgrade transactions?")
+ protocol = Param.Coherence("name of coherence protocol")
diff --git a/src/mem/cache/coherence/SConscript b/src/mem/cache/coherence/SConscript
index 03a2d85d7..4f5966140 100644
--- a/src/mem/cache/coherence/SConscript
+++ b/src/mem/cache/coherence/SConscript
@@ -30,6 +30,8 @@
Import('*')
+SimObject('CoherenceProtocol.py')
+
Source('coherence_protocol.cc')
Source('uni_coherence.cc')
diff --git a/src/mem/cache/tags/Repl.py b/src/mem/cache/tags/Repl.py
new file mode 100644
index 000000000..b76aa1d6e
--- /dev/null
+++ b/src/mem/cache/tags/Repl.py
@@ -0,0 +1,11 @@
+from m5.SimObject import SimObject
+from m5.params import *
+class Repl(SimObject):
+ type = 'Repl'
+ abstract = True
+
+class GenRepl(Repl):
+ type = 'GenRepl'
+ fresh_res = Param.Int("Fresh pool residency time")
+ num_pools = Param.Int("Number of priority pools")
+ pool_res = Param.Int("Pool residency time")
diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript
index baf71f687..3fcaec4fa 100644
--- a/src/mem/cache/tags/SConscript
+++ b/src/mem/cache/tags/SConscript
@@ -38,5 +38,6 @@ Source('split.cc')
Source('split_lifo.cc')
Source('split_lru.cc')
+SimObject('Repl.py')
Source('repl/gen.cc')
Source('repl/repl.cc')
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
index 2463a19ba..f70c0cec3 100644
--- a/src/mem/packet.cc
+++ b/src/mem/packet.cc
@@ -192,11 +192,12 @@ fixPacket(PacketPtr func, PacketPtr timing)
func->flags |= SATISFIED;
return false;
} else {
- // In this case the timing packet only partially satisfies the
- // requset, so we would need more information to make this work.
- // Like bytes valid in the packet or something, so the request could
- // continue and get this bit of possibly newer data along with the
- // older data not written to yet.
+ // In this case the timing packet only partially satisfies
+ // the request, so we would need more information to make
+ // this work. Like bytes valid in the packet or
+ // something, so the request could continue and get this
+ // bit of possibly newer data along with the older data
+ // not written to yet.
panic("Timing packet only partially satisfies the functional"
"request. Now what?");
}
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index dc23e9f6d..c1e6a1e7f 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -506,16 +506,18 @@ class Packet
bool intersect(PacketPtr p);
};
-/** This function given a functional packet and a timing packet either satisfies
- * the timing packet, or updates the timing packet to reflect the updated state
- * in the timing packet. It returns if the functional packet should continue to
- * traverse the memory hierarchy or not.
+/** This function given a functional packet and a timing packet either
+ * satisfies the timing packet, or updates the timing packet to
+ * reflect the updated state in the timing packet. It returns if the
+ * functional packet should continue to traverse the memory hierarchy
+ * or not.
*/
bool fixPacket(PacketPtr func, PacketPtr timing);
-/** This function is a wrapper for the fixPacket field that toggles the hasData bit
- * it is used when a response is waiting in the caches, but hasn't been marked as a
- * response yet (so the fixPacket needs to get the correct value for the hasData)
+/** This function is a wrapper for the fixPacket field that toggles
+ * the hasData bit it is used when a response is waiting in the
+ * caches, but hasn't been marked as a response yet (so the fixPacket
+ * needs to get the correct value for the hasData)
*/
bool fixDelayedResponsePacket(PacketPtr func, PacketPtr timing);
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 6621c36cf..9d840fe69 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -414,20 +414,7 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
void
PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
{
- //Since we are overriding the function, make sure to have the impl of the
- //check or functional accesses here.
- std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
- std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
- bool notDone = true;
-
- while (i != end && notDone) {
- PacketPtr target = i->second;
- // If the target contains data, and it overlaps the
- // probed request, need to update data
- if (target->intersect(pkt))
- notDone = fixPacket(pkt, target);
- i++;
- }
+ checkFunctional(pkt);
// Default implementation of SimpleTimingPort::recvFunctional()
// calls recvAtomic() and throws away the latency; we can save a
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
index 9a4bd7967..ed4c0c172 100644
--- a/src/mem/tport.cc
+++ b/src/mem/tport.cc
@@ -31,23 +31,30 @@
#include "mem/tport.hh"
void
-SimpleTimingPort::recvFunctional(PacketPtr pkt)
+SimpleTimingPort::checkFunctional(PacketPtr pkt)
{
- std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
- std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
- bool notDone = true;
+ DeferredPacketIterator i = transmitList.begin();
+ DeferredPacketIterator end = transmitList.end();
- while (i != end && notDone) {
- PacketPtr target = i->second;
+ for (; i != end; ++i) {
+ PacketPtr target = i->pkt;
// If the target contains data, and it overlaps the
// probed request, need to update data
- if (target->intersect(pkt))
- notDone = fixPacket(pkt, target);
-
- i++;
+ if (target->intersect(pkt)) {
+ if (!fixPacket(pkt, target)) {
+ // fixPacket returns true for continue, false for done
+ return;
+ }
+ }
}
+}
- //Then just do an atomic access and throw away the returned latency
+void
+SimpleTimingPort::recvFunctional(PacketPtr pkt)
+{
+ checkFunctional(pkt);
+
+ // Just do an atomic access and throw away the returned latency
if (pkt->result != Packet::Success)
recvAtomic(pkt);
}
@@ -65,93 +72,94 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
// turn packet around to go back to requester if response expected
if (pkt->needsResponse()) {
pkt->makeTimingResponse();
- sendTiming(pkt, latency);
+ schedSendTiming(pkt, curTick + latency);
}
- else {
- if (pkt->cmd != MemCmd::UpgradeReq)
- {
- delete pkt->req;
- delete pkt;
- }
+ else if (pkt->cmd != MemCmd::UpgradeReq) {
+ delete pkt->req;
+ delete pkt;
}
return true;
}
-void
-SimpleTimingPort::recvRetry()
-{
- assert(!transmitList.empty());
- if (Port::sendTiming(transmitList.front().second)) {
- transmitList.pop_front();
- DPRINTF(Bus, "No Longer waiting on retry\n");
- if (!transmitList.empty()) {
- Tick time = transmitList.front().first;
- sendEvent.schedule(time <= curTick ? curTick+1 : time);
- }
- }
-
- if (transmitList.empty() && drainEvent) {
- drainEvent->process();
- drainEvent = NULL;
- }
-}
void
-SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
+SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
{
+ assert(when > curTick);
+
// Nothing is on the list: add it and schedule an event
if (transmitList.empty()) {
- assert(!sendEvent.scheduled());
- sendEvent.schedule(curTick+time);
- transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ assert(!sendEvent->scheduled());
+ sendEvent->schedule(when);
+ transmitList.push_back(DeferredPacket(when, pkt));
return;
}
// something is on the list and this belongs at the end
- if (time+curTick >= transmitList.back().first) {
- transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ if (when >= transmitList.back().tick) {
+ transmitList.push_back(DeferredPacket(when, pkt));
return;
}
// Something is on the list and this belongs somewhere else
- std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
- std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
- bool done = false;
+ DeferredPacketIterator i = transmitList.begin();
+ DeferredPacketIterator end = transmitList.end();
- while (i != end && !done) {
- if (time+curTick < i->first) {
+ for (; i != end; ++i) {
+ if (when < i->tick) {
if (i == transmitList.begin()) {
//Inserting at begining, reschedule
- sendEvent.reschedule(time+curTick);
+ sendEvent->reschedule(when);
}
- transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt));
- done = true;
+ transmitList.insert(i, DeferredPacket(when, pkt));
+ return;
}
- i++;
}
- assert(done);
+ assert(false); // should never get here
}
+
void
-SimpleTimingPort::SendEvent::process()
+SimpleTimingPort::sendDeferredPacket()
{
- assert(port->transmitList.size());
- assert(port->transmitList.front().first <= curTick);
- if (port->Port::sendTiming(port->transmitList.front().second)) {
+ assert(deferredPacketReady());
+ bool success = sendTiming(transmitList.front().pkt);
+
+ if (success) {
//send successful, remove packet
- port->transmitList.pop_front();
- if (!port->transmitList.empty()) {
- Tick time = port->transmitList.front().first;
- schedule(time <= curTick ? curTick+1 : time);
+ transmitList.pop_front();
+ if (!transmitList.empty()) {
+ Tick time = transmitList.front().tick;
+ sendEvent->schedule(time <= curTick ? curTick+1 : time);
}
- if (port->transmitList.empty() && port->drainEvent) {
- port->drainEvent->process();
- port->drainEvent = NULL;
+
+ if (transmitList.empty() && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
}
- return;
}
- // send unsuccessful (due to flow control). Will get retry
- // callback later; save for then if not already
- DPRINTF(Bus, "Waiting on retry\n");
+
+ waitingOnRetry = !success;
+
+ if (waitingOnRetry) {
+ DPRINTF(Bus, "Send failed, waiting on retry\n");
+ }
+}
+
+
+void
+SimpleTimingPort::recvRetry()
+{
+ DPRINTF(Bus, "Received retry\n");
+ assert(waitingOnRetry);
+ sendDeferredPacket();
+}
+
+
+void
+SimpleTimingPort::processSendEvent()
+{
+ assert(!waitingOnRetry);
+ sendDeferredPacket();
}
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
index 3d28ea3e5..ea0f05ed1 100644
--- a/src/mem/tport.hh
+++ b/src/mem/tport.hh
@@ -58,9 +58,26 @@
class SimpleTimingPort : public Port
{
protected:
+ /** A deferred packet, buffered to transmit later. */
+ class DeferredPacket {
+ public:
+ Tick tick; ///< The tick when the packet is ready to transmit
+ PacketPtr pkt; ///< Pointer to the packet to transmit
+ DeferredPacket(Tick t, PacketPtr p)
+ : tick(t), pkt(p)
+ {}
+ };
+
+ typedef std::list<DeferredPacket> DeferredPacketList;
+ typedef std::list<DeferredPacket>::iterator DeferredPacketIterator;
+
/** A list of outgoing timing response packets that haven't been
* serviced yet. */
- std::list<std::pair<Tick,PacketPtr> > transmitList;
+ DeferredPacketList transmitList;
+
+ /** This function attempts to send deferred packets. Scheduled to
+ * be called in the future via SendEvent. */
+ void processSendEvent();
/**
* This class is used to implemented sendTiming() with a delay. When
@@ -68,32 +85,38 @@ class SimpleTimingPort : public Port
* When the event time expires it attempts to send the packet.
* If it cannot, the packet sent when recvRetry() is called.
**/
- class SendEvent : public Event
- {
- SimpleTimingPort *port;
-
- public:
- SendEvent(SimpleTimingPort *p)
- : Event(&mainEventQueue), port(p)
- { }
-
- virtual void process();
+ typedef EventWrapper<SimpleTimingPort, &SimpleTimingPort::processSendEvent>
+ SendEvent;
- virtual const char *description()
- { return "Future scheduled sendTiming event"; }
- };
-
- SendEvent sendEvent;
+ Event *sendEvent;
/** If we need to drain, keep the drain event around until we're done
* here.*/
Event *drainEvent;
+ /** Remember whether we're awaiting a retry from the bus. */
+ bool waitingOnRetry;
+
+ /** Check the list of buffered packets against the supplied
+ * functional request. */
+ void checkFunctional(PacketPtr funcPkt);
+
+ /** Check whether we have a packet ready to go on the transmit list. */
+ bool deferredPacketReady()
+ { return !transmitList.empty() && transmitList.front().tick <= curTick; }
+
/** Schedule a sendTiming() event to be called in the future.
* @param pkt packet to send
- * @param time increment from now (in ticks) to send packet
+ * @param absolute time (in ticks) to send packet
+ */
+ void schedSendTiming(PacketPtr pkt, Tick when);
+
+ /** Attempt to send the packet at the head of the deferred packet
+ * list. Caller must guarantee that the deferred packet list is
+ * non-empty and that the head packet is scheduled for curTick (or
+ * earlier).
*/
- void sendTiming(PacketPtr pkt, Tick time);
+ void sendDeferredPacket();
/** This function is notification that the device should attempt to send a
* packet again. */
@@ -115,9 +138,14 @@ class SimpleTimingPort : public Port
public:
SimpleTimingPort(std::string pname, MemObject *_owner = NULL)
- : Port(pname, _owner), sendEvent(this), drainEvent(NULL)
+ : Port(pname, _owner),
+ sendEvent(new SendEvent(this)),
+ drainEvent(NULL),
+ waitingOnRetry(false)
{}
+ ~SimpleTimingPort() { delete sendEvent; }
+
/** Hook for draining timing accesses from the system. The
* associated SimObject's drain() functions should be implemented
* something like this when this class is used: