summaryrefslogtreecommitdiff
path: root/src/mem/coherent_bus.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2013-05-30 12:54:01 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2013-05-30 12:54:01 -0400
commit2308f812ef848d027b99dd52c0900aed11260d87 (patch)
tree8f2dfe7b5345e74eb1b0b3ebb7417a5587ba5395 /src/mem/coherent_bus.cc
parente82996d9dad5ac38fe2c8709c05b26cf92d356e8 (diff)
downloadgem5-2308f812ef848d027b99dd52c0900aed11260d87.tar.xz
mem: Make the buses multi layered
This patch makes the buses multi layered, and effectively creates a crossbar structure with distributed contention ports at the destination ports. Before this patch, a bus could have a single request, response and snoop response in flight at any time, and with these changes there can be as many requests as connected slaves (bus master ports), and as many responses as connected masters (bus slave ports). Together with address interleaving, this patch enables us to create high-throughput memory interconnects, e.g. 50+ GByte/s.
Diffstat (limited to 'src/mem/coherent_bus.cc')
-rw-r--r--src/mem/coherent_bus.cc74
1 files changed, 50 insertions, 24 deletions
diff --git a/src/mem/coherent_bus.cc b/src/mem/coherent_bus.cc
index 923fa08d6..20597bc3a 100644
--- a/src/mem/coherent_bus.cc
+++ b/src/mem/coherent_bus.cc
@@ -55,14 +55,7 @@
#include "sim/system.hh"
CoherentBus::CoherentBus(const CoherentBusParams *p)
- : BaseBus(p),
- reqLayer(*this, ".reqLayer", p->port_master_connection_count +
- p->port_default_connection_count),
- respLayer(*this, ".respLayer", p->port_slave_connection_count),
- snoopRespLayer(*this, ".snoopRespLayer",
- p->port_master_connection_count +
- p->port_default_connection_count),
- system(p->system)
+ : BaseBus(p), system(p->system)
{
// create the ports based on the size of the master and slave
// vector ports, and the presence of the default port, the ports
@@ -71,6 +64,10 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
std::string portName = csprintf("%s.master[%d]", name(), i);
MasterPort* bp = new CoherentBusMasterPort(portName, *this, i);
masterPorts.push_back(bp);
+ reqLayers.push_back(new ReqLayer(*bp, *this,
+ csprintf(".reqLayer%d", i)));
+ snoopLayers.push_back(new SnoopLayer(*bp, *this,
+ csprintf(".snoopLayer%d", i)));
}
// see if we have a default slave device connected and if so add
@@ -81,6 +78,11 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
MasterPort* bp = new CoherentBusMasterPort(portName, *this,
defaultPortID);
masterPorts.push_back(bp);
+ reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
+ defaultPortID)));
+ snoopLayers.push_back(new SnoopLayer(*bp, *this,
+ csprintf(".snoopLayer%d",
+ defaultPortID)));
}
// create the slave ports, once again starting at zero
@@ -88,11 +90,23 @@ CoherentBus::CoherentBus(const CoherentBusParams *p)
std::string portName = csprintf("%s.slave[%d]", name(), i);
SlavePort* bp = new CoherentBusSlavePort(portName, *this, i);
slavePorts.push_back(bp);
+ respLayers.push_back(new RespLayer(*bp, *this,
+ csprintf(".respLayer%d", i)));
}
clearPortCache();
}
+CoherentBus::~CoherentBus()
+{
+ for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
+ delete *l;
+ for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
+ delete *l;
+ for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
+ delete *l;
+}
+
void
CoherentBus::init()
{
@@ -129,7 +143,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
// test if the bus should be considered occupied for the current
// port, and exclude express snoops from the check
- if (!is_express_snoop && !reqLayer.tryTiming(src_port, master_port_id)) {
+ if (!is_express_snoop && !reqLayers[master_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUS BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
@@ -198,11 +212,11 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
src_port->name(), pkt->cmdString(), pkt->getAddr());
// update the bus state and schedule an idle event
- reqLayer.failedTiming(src_port, master_port_id,
- clockEdge(headerCycles));
+ reqLayers[master_port_id]->failedTiming(src_port,
+ clockEdge(headerCycles));
} else {
// update the bus state and schedule an idle event
- reqLayer.succeededTiming(packetFinishTime);
+ reqLayers[master_port_id]->succeededTiming(packetFinishTime);
dataThroughBus += pkt_size;
}
}
@@ -228,7 +242,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
// test if the bus should be considered occupied for the current
// port
- if (!respLayer.tryTiming(src_port, slave_port_id)) {
+ if (!respLayers[slave_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
@@ -259,7 +273,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id)
// deadlock
assert(success);
- respLayer.succeededTiming(packetFinishTime);
+ respLayers[slave_port_id]->succeededTiming(packetFinishTime);
// stats updates
dataThroughBus += pkt_size;
@@ -318,10 +332,12 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
// port, note that the check is bypassed if the response is being
// passed on as a normal response since this is occupying the
// response layer rather than the snoop response layer
- if (forwardAsSnoop && !snoopRespLayer.tryTiming(src_port, dest_port_id)) {
- DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
- src_port->name(), pkt->cmdString(), pkt->getAddr());
- return false;
+ if (forwardAsSnoop) {
+ if (!snoopLayers[dest_port_id]->tryTiming(src_port)) {
+ DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
+ src_port->name(), pkt->cmdString(), pkt->getAddr());
+ return false;
+ }
}
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x\n",
@@ -349,7 +365,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
totPktSize[slave_port_id][dest_port_id] += pkt_size;
assert(success);
- snoopRespLayer.succeededTiming(packetFinishTime);
+ snoopLayers[dest_port_id]->succeededTiming(packetFinishTime);
} else {
// we got a snoop response on one of our slave ports,
// i.e. from a coherent master connected to the bus, and
@@ -416,7 +432,7 @@ CoherentBus::recvRetry(PortID master_port_id)
// responses and snoop responses never block on forwarding them,
// so the retry will always be coming from a port to which we
// tried to forward a request
- reqLayer.recvRetry(master_port_id);
+ reqLayers[master_port_id]->recvRetry();
}
Tick
@@ -606,7 +622,14 @@ unsigned int
CoherentBus::drain(DrainManager *dm)
{
// sum up the individual layers
- return reqLayer.drain(dm) + respLayer.drain(dm) + snoopRespLayer.drain(dm);
+ unsigned int total = 0;
+ for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
+ total += (*l)->drain(dm);
+ for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
+ total += (*l)->drain(dm);
+ for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
+ total += (*l)->drain(dm);
+ return total;
}
void
@@ -614,9 +637,12 @@ CoherentBus::regStats()
{
// register the stats of the base class and our three bus layers
BaseBus::regStats();
- reqLayer.regStats();
- respLayer.regStats();
- snoopRespLayer.regStats();
+ for (auto l = reqLayers.begin(); l != reqLayers.end(); ++l)
+ (*l)->regStats();
+ for (auto l = respLayers.begin(); l != respLayers.end(); ++l)
+ (*l)->regStats();
+ for (auto l = snoopLayers.begin(); l != snoopLayers.end(); ++l)
+ (*l)->regStats();
dataThroughBus
.name(name() + ".data_through_bus")