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

@@ -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")

View File

@@ -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);

View File

@@ -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;