summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2012-07-12 12:56:13 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2012-07-12 12:56:13 -0400
commitf00cba34eb8e6bf947721f72de314f4e8bd6a8f8 (patch)
tree432ab17d82d72d5042758f25066dc64558c9a7f8
parent55bfe13705a3eccdffb6846dd87df5f190b04c99 (diff)
downloadgem5-f00cba34eb8e6bf947721f72de314f4e8bd6a8f8.tar.xz
Mem: Make SimpleMemory single ported
This patch changes the simple memory to have a single slave port rather than a vector port. The simple memory makes no attempts at modelling the contention between multiple ports, and any such multiplexing and demultiplexing could be done in a bus (or crossbar) outside the memory controller. This scenario also matches with the ongoing work on a SimpleDRAM model, which will be a single-ported single-channel controller that can be used in conjunction with a bus (or crossbar) to create a multi-port multi-channel controller. There are only very few regressions that make use of the vector port, and these are all for functional accesses only. To facilitate these cases, memtest and memtest-ruby have been updated to also have a "functional" bus to perform the (de)multiplexing of the functional memory accesses.
-rw-r--r--configs/example/memtest.py6
-rw-r--r--configs/example/ruby_mem_test.py8
-rw-r--r--src/mem/SimpleMemory.py2
-rw-r--r--src/mem/simple_mem.cc29
-rw-r--r--src/mem/simple_mem.hh9
-rw-r--r--tests/configs/memtest-ruby.py6
-rw-r--r--tests/configs/memtest.py6
7 files changed, 34 insertions, 32 deletions
diff --git a/configs/example/memtest.py b/configs/example/memtest.py
index 590378920..4f57ef063 100644
--- a/configs/example/memtest.py
+++ b/configs/example/memtest.py
@@ -141,6 +141,7 @@ for scale in treespec[:-2]:
# system simulated
system = System(funcmem = SimpleMemory(in_addr_map = False),
+ funcbus = NoncoherentBus(),
physmem = SimpleMemory(latency = "100ns"))
def make_level(spec, prototypes, attach_obj, attach_port):
@@ -169,10 +170,13 @@ def make_level(spec, prototypes, attach_obj, attach_port):
parent.cpu = objs
for t in objs:
t.test = getattr(attach_obj, attach_port)
- t.functional = system.funcmem.port
+ t.functional = system.funcbus.slave
make_level(treespec, prototypes, system.physmem, "port")
+# connect reference memory to funcbus
+system.funcbus.master = system.funcmem.port
+
# -----------------------
# run simulation
# -----------------------
diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py
index e3dab955c..858d13ee8 100644
--- a/configs/example/ruby_mem_test.py
+++ b/configs/example/ruby_mem_test.py
@@ -107,6 +107,7 @@ cpus = [ MemTest(atomic = False,
system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False),
+ funcbus = NoncoherentBus(),
physmem = SimpleMemory())
if options.num_dmas > 0:
@@ -141,7 +142,7 @@ for (i, cpu) in enumerate(cpus):
# Tie the cpu memtester ports to the correct system ports
#
cpu.test = system.ruby._cpu_ruby_ports[i].slave
- cpu.functional = system.funcmem.port
+ cpu.functional = system.funcbus.slave
#
# Since the memtester is incredibly bursty, increase the deadlock
@@ -160,7 +161,10 @@ for (i, dma) in enumerate(dmas):
# Tie the dma memtester ports to the correct functional port
# Note that the test port has already been connected to the dma_sequencer
#
- dma.functional = system.funcmem.port
+ dma.functional = system.funcbus.slave
+
+# connect reference memory to funcbus
+system.funcbus.master = system.funcmem.port
# -----------------------
# run simulation
diff --git a/src/mem/SimpleMemory.py b/src/mem/SimpleMemory.py
index 51de3374d..c47d04222 100644
--- a/src/mem/SimpleMemory.py
+++ b/src/mem/SimpleMemory.py
@@ -44,6 +44,6 @@ from AbstractMemory import *
class SimpleMemory(AbstractMemory):
type = 'SimpleMemory'
- port = VectorSlavePort("Slave ports")
+ port = SlavePort("Slave ports")
latency = Param.Latency('30ns', "Request to response latency")
latency_var = Param.Latency('0ns', "Request to response latency variance")
diff --git a/src/mem/simple_mem.cc b/src/mem/simple_mem.cc
index aa9168bf7..b9db64276 100644
--- a/src/mem/simple_mem.cc
+++ b/src/mem/simple_mem.cc
@@ -49,24 +49,17 @@ using namespace std;
SimpleMemory::SimpleMemory(const Params* p) :
AbstractMemory(p),
- lat(p->latency), lat_var(p->latency_var)
+ port(name() + ".port", *this), lat(p->latency), lat_var(p->latency_var)
{
- for (size_t i = 0; i < p->port_port_connection_count; ++i) {
- ports.push_back(new MemoryPort(csprintf("%s-port-%d", name(), i),
- *this));
- }
}
void
SimpleMemory::init()
{
- for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end();
- ++p) {
- if (!(*p)->isConnected()) {
- fatal("SimpleMemory port %s is unconnected!\n", (*p)->name());
- } else {
- (*p)->sendRangeChange();
- }
+ // allow unconnected memories as this is used in several ruby
+ // systems at the moment
+ if (port.isConnected()) {
+ port.sendRangeChange();
}
}
@@ -102,22 +95,14 @@ SimpleMemory::getSlavePort(const std::string &if_name, int idx)
if (if_name != "port") {
return MemObject::getSlavePort(if_name, idx);
} else {
- if (idx >= static_cast<int>(ports.size())) {
- fatal("SimpleMemory::getSlavePort: unknown index %d\n", idx);
- }
-
- return *ports[idx];
+ return port;
}
}
unsigned int
SimpleMemory::drain(Event *de)
{
- int count = 0;
- for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end();
- ++p) {
- count += (*p)->drain(de);
- }
+ int count = port.drain(de);
if (count)
changeState(Draining);
diff --git a/src/mem/simple_mem.hh b/src/mem/simple_mem.hh
index 5f136ed51..95bfa57ad 100644
--- a/src/mem/simple_mem.hh
+++ b/src/mem/simple_mem.hh
@@ -54,9 +54,10 @@
#include "params/SimpleMemory.hh"
/**
- * The simple memory is a basic multi-ported memory with an infinite
- * throughput and a fixed latency, potentially with a variance added
- * to it. It uses a SimpleTimingPort to implement the timing accesses.
+ * The simple memory is a basic single-ported memory controller with
+ * an infinite throughput and a fixed latency, potentially with a
+ * variance added to it. It uses a SimpleTimingPort to implement the
+ * timing accesses.
*/
class SimpleMemory : public AbstractMemory
{
@@ -81,7 +82,7 @@ class SimpleMemory : public AbstractMemory
};
- std::vector<MemoryPort*> ports;
+ MemoryPort port;
Tick lat;
Tick lat_var;
diff --git a/tests/configs/memtest-ruby.py b/tests/configs/memtest-ruby.py
index 008daa1ad..560a8fd65 100644
--- a/tests/configs/memtest-ruby.py
+++ b/tests/configs/memtest-ruby.py
@@ -79,6 +79,7 @@ options.num_cpus = nb_cores
# system simulated
system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False),
+ funcbus = NoncoherentBus(),
physmem = SimpleMemory())
Ruby.create_system(options, system)
@@ -91,7 +92,7 @@ for (i, ruby_port) in enumerate(system.ruby._cpu_ruby_ports):
# physmem, respectively
#
cpus[i].test = ruby_port.slave
- cpus[i].functional = system.funcmem.port
+ cpus[i].functional = system.funcbus.slave
#
# Since the memtester is incredibly bursty, increase the deadlock
@@ -105,6 +106,9 @@ for (i, ruby_port) in enumerate(system.ruby._cpu_ruby_ports):
#
ruby_port.access_phys_mem = False
+# connect reference memory to funcbus
+system.funcmem.port = system.funcbus.master
+
# -----------------------
# run simulation
# -----------------------
diff --git a/tests/configs/memtest.py b/tests/configs/memtest.py
index 0add2158f..57f45b1d4 100644
--- a/tests/configs/memtest.py
+++ b/tests/configs/memtest.py
@@ -57,6 +57,7 @@ cpus = [ MemTest() for i in xrange(nb_cores) ]
# system simulated
system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
+ funcbus = NoncoherentBus(),
physmem = SimpleMemory(),
membus = CoherentBus(clock="500GHz", width=16))
@@ -73,10 +74,13 @@ for cpu in cpus:
cpu.l1c = L1(size = '32kB', assoc = 4)
cpu.l1c.cpu_side = cpu.test
cpu.l1c.mem_side = system.toL2Bus.slave
- system.funcmem.port = cpu.functional
+ system.funcbus.slave = cpu.functional
system.system_port = system.membus.slave
+# connect reference memory to funcbus
+system.funcmem.port = system.funcbus.master
+
# connect memory to membus
system.physmem.port = system.membus.master