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.
This commit is contained in:
Andreas Hansson 2012-07-12 12:56:13 -04:00
parent 55bfe13705
commit f00cba34eb
7 changed files with 34 additions and 32 deletions

View file

@ -141,6 +141,7 @@ for scale in treespec[:-2]:
# system simulated # system simulated
system = System(funcmem = SimpleMemory(in_addr_map = False), system = System(funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
physmem = SimpleMemory(latency = "100ns")) physmem = SimpleMemory(latency = "100ns"))
def make_level(spec, prototypes, attach_obj, attach_port): 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 parent.cpu = objs
for t in objs: for t in objs:
t.test = getattr(attach_obj, attach_port) t.test = getattr(attach_obj, attach_port)
t.functional = system.funcmem.port t.functional = system.funcbus.slave
make_level(treespec, prototypes, system.physmem, "port") make_level(treespec, prototypes, system.physmem, "port")
# connect reference memory to funcbus
system.funcbus.master = system.funcmem.port
# ----------------------- # -----------------------
# run simulation # run simulation
# ----------------------- # -----------------------

View file

@ -107,6 +107,7 @@ cpus = [ MemTest(atomic = False,
system = System(cpu = cpus, system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False), funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
physmem = SimpleMemory()) physmem = SimpleMemory())
if options.num_dmas > 0: 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 # Tie the cpu memtester ports to the correct system ports
# #
cpu.test = system.ruby._cpu_ruby_ports[i].slave 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 # 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 # Tie the dma memtester ports to the correct functional port
# Note that the test port has already been connected to the dma_sequencer # 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 # run simulation

View file

@ -44,6 +44,6 @@ from AbstractMemory import *
class SimpleMemory(AbstractMemory): class SimpleMemory(AbstractMemory):
type = 'SimpleMemory' type = 'SimpleMemory'
port = VectorSlavePort("Slave ports") port = SlavePort("Slave ports")
latency = Param.Latency('30ns', "Request to response latency") latency = Param.Latency('30ns', "Request to response latency")
latency_var = Param.Latency('0ns', "Request to response latency variance") latency_var = Param.Latency('0ns', "Request to response latency variance")

View file

@ -49,24 +49,17 @@ using namespace std;
SimpleMemory::SimpleMemory(const Params* p) : SimpleMemory::SimpleMemory(const Params* p) :
AbstractMemory(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 void
SimpleMemory::init() SimpleMemory::init()
{ {
for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end(); // allow unconnected memories as this is used in several ruby
++p) { // systems at the moment
if (!(*p)->isConnected()) { if (port.isConnected()) {
fatal("SimpleMemory port %s is unconnected!\n", (*p)->name()); port.sendRangeChange();
} else {
(*p)->sendRangeChange();
}
} }
} }
@ -102,22 +95,14 @@ SimpleMemory::getSlavePort(const std::string &if_name, int idx)
if (if_name != "port") { if (if_name != "port") {
return MemObject::getSlavePort(if_name, idx); return MemObject::getSlavePort(if_name, idx);
} else { } else {
if (idx >= static_cast<int>(ports.size())) { return port;
fatal("SimpleMemory::getSlavePort: unknown index %d\n", idx);
}
return *ports[idx];
} }
} }
unsigned int unsigned int
SimpleMemory::drain(Event *de) SimpleMemory::drain(Event *de)
{ {
int count = 0; int count = port.drain(de);
for (vector<MemoryPort*>::iterator p = ports.begin(); p != ports.end();
++p) {
count += (*p)->drain(de);
}
if (count) if (count)
changeState(Draining); changeState(Draining);

View file

@ -54,9 +54,10 @@
#include "params/SimpleMemory.hh" #include "params/SimpleMemory.hh"
/** /**
* The simple memory is a basic multi-ported memory with an infinite * The simple memory is a basic single-ported memory controller with
* throughput and a fixed latency, potentially with a variance added * an infinite throughput and a fixed latency, potentially with a
* to it. It uses a SimpleTimingPort to implement the timing accesses. * variance added to it. It uses a SimpleTimingPort to implement the
* timing accesses.
*/ */
class SimpleMemory : public AbstractMemory class SimpleMemory : public AbstractMemory
{ {
@ -81,7 +82,7 @@ class SimpleMemory : public AbstractMemory
}; };
std::vector<MemoryPort*> ports; MemoryPort port;
Tick lat; Tick lat;
Tick lat_var; Tick lat_var;

View file

@ -79,6 +79,7 @@ options.num_cpus = nb_cores
# system simulated # system simulated
system = System(cpu = cpus, system = System(cpu = cpus,
funcmem = SimpleMemory(in_addr_map = False), funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
physmem = SimpleMemory()) physmem = SimpleMemory())
Ruby.create_system(options, system) Ruby.create_system(options, system)
@ -91,7 +92,7 @@ for (i, ruby_port) in enumerate(system.ruby._cpu_ruby_ports):
# physmem, respectively # physmem, respectively
# #
cpus[i].test = ruby_port.slave 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 # 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 ruby_port.access_phys_mem = False
# connect reference memory to funcbus
system.funcmem.port = system.funcbus.master
# ----------------------- # -----------------------
# run simulation # run simulation
# ----------------------- # -----------------------

View file

@ -57,6 +57,7 @@ cpus = [ MemTest() for i in xrange(nb_cores) ]
# system simulated # system simulated
system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False), system = System(cpu = cpus, funcmem = SimpleMemory(in_addr_map = False),
funcbus = NoncoherentBus(),
physmem = SimpleMemory(), physmem = SimpleMemory(),
membus = CoherentBus(clock="500GHz", width=16)) membus = CoherentBus(clock="500GHz", width=16))
@ -73,10 +74,13 @@ for cpu in cpus:
cpu.l1c = L1(size = '32kB', assoc = 4) cpu.l1c = L1(size = '32kB', assoc = 4)
cpu.l1c.cpu_side = cpu.test cpu.l1c.cpu_side = cpu.test
cpu.l1c.mem_side = system.toL2Bus.slave cpu.l1c.mem_side = system.toL2Bus.slave
system.funcmem.port = cpu.functional system.funcbus.slave = cpu.functional
system.system_port = system.membus.slave system.system_port = system.membus.slave
# connect reference memory to funcbus
system.funcmem.port = system.funcbus.master
# connect memory to membus # connect memory to membus
system.physmem.port = system.membus.master system.physmem.port = system.membus.master