From 2308f812ef848d027b99dd52c0900aed11260d87 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Thu, 30 May 2013 12:54:01 -0400 Subject: 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. --- src/mem/bus.cc | 81 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 42 deletions(-) (limited to 'src/mem/bus.cc') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 3fa7c7231..855f82db4 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -156,18 +156,17 @@ BaseBus::calcPacketTiming(PacketPtr pkt) offset; } -template -BaseBus::Layer::Layer(BaseBus& _bus, const std::string& _name, - uint16_t num_dest_ports) : - Drainable(), - bus(_bus), _name(_name), state(IDLE), drainManager(NULL), - retryingPort(NULL), waitingForPeer(num_dest_ports, NULL), +template +BaseBus::Layer::Layer(DstType& _port, BaseBus& _bus, + const std::string& _name) : + port(_port), bus(_bus), _name(_name), state(IDLE), drainManager(NULL), + retryingPort(NULL), waitingForPeer(NULL), releaseEvent(this) { } -template -void BaseBus::Layer::occupyLayer(Tick until) +template +void BaseBus::Layer::occupyLayer(Tick until) { // ensure the state is busy at this point, as the bus should // transition from idle as soon as it has decided to forward the @@ -186,21 +185,21 @@ void BaseBus::Layer::occupyLayer(Tick until) curTick(), until); } -template +template bool -BaseBus::Layer::tryTiming(PortClass* port, PortID dest_port_id) +BaseBus::Layer::tryTiming(SrcType* src_port) { - // first we see if the bus is busy, next we check if we are in a + // first we see if the layer is busy, next we check if we are in a // retry with a port other than the current one, lastly we check // if the destination port is already engaged in a transaction // waiting for a retry from the peer - if (state == BUSY || (state == RETRY && port != retryingPort) || - waitingForPeer[dest_port_id] != NULL) { + if (state == BUSY || (state == RETRY && src_port != retryingPort) || + waitingForPeer != NULL) { // put the port at the end of the retry list waiting for the // layer to be freed up (and in the case of a busy peer, for // that transaction to go through, and then the bus to free // up) - waitingForLayer.push_back(port); + waitingForLayer.push_back(src_port); return false; } @@ -213,9 +212,9 @@ BaseBus::Layer::tryTiming(PortClass* port, PortID dest_port_id) return true; } -template +template void -BaseBus::Layer::succeededTiming(Tick busy_time) +BaseBus::Layer::succeededTiming(Tick busy_time) { // we should have gone from idle or retry to busy in the tryTiming // test @@ -225,19 +224,19 @@ BaseBus::Layer::succeededTiming(Tick busy_time) occupyLayer(busy_time); } -template +template void -BaseBus::Layer::failedTiming(PortClass* src_port, - PortID dest_port_id, Tick busy_time) +BaseBus::Layer::failedTiming(SrcType* src_port, + Tick busy_time) { // ensure no one got in between and tried to send something to // this port - assert(waitingForPeer[dest_port_id] == NULL); + assert(waitingForPeer == NULL); // if the source port is the current retrying one or not, we have // failed in forwarding and should track that we are now waiting // for the peer to send a retry - waitingForPeer[dest_port_id] = src_port; + waitingForPeer = src_port; // we should have gone from idle or retry to busy in the tryTiming // test @@ -247,9 +246,9 @@ BaseBus::Layer::failedTiming(PortClass* src_port, occupyLayer(busy_time); } -template +template void -BaseBus::Layer::releaseLayer() +BaseBus::Layer::releaseLayer() { // releasing the bus means we should now be idle assert(state == BUSY); @@ -270,9 +269,9 @@ BaseBus::Layer::releaseLayer() } } -template +template void -BaseBus::Layer::retryWaiting() +BaseBus::Layer::retryWaiting() { // this should never be called with no one waiting assert(!waitingForLayer.empty()); @@ -306,23 +305,21 @@ BaseBus::Layer::retryWaiting() } } -template +template void -BaseBus::Layer::recvRetry(PortID port_id) +BaseBus::Layer::recvRetry() { // we should never get a retry without having failed to forward // something to this port - assert(waitingForPeer[port_id] != NULL); + assert(waitingForPeer != NULL); - // find the port where the failed packet originated and remove the - // item from the waiting list - PortClass* retry_port = waitingForPeer[port_id]; - waitingForPeer[port_id] = NULL; + // add the port where the failed packet originated to the front of + // the waiting ports for the layer, this allows us to call retry + // on the port immediately if the bus layer is idle + waitingForLayer.push_front(waitingForPeer); - // add this port at the front of the waiting ports for the layer, - // this allows us to call retry on the port immediately if the bus - // layer is idle - waitingForLayer.push_front(retry_port); + // we are no longer waiting for the peer + waitingForPeer = NULL; // if the bus layer is idle, retry this port straight away, if we // are busy, then simply let the port wait for its turn @@ -606,9 +603,9 @@ BaseBus::regStats() } } -template +template unsigned int -BaseBus::Layer::drain(DrainManager *dm) +BaseBus::Layer::drain(DrainManager *dm) { //We should check that we're not "doing" anything, and that noone is //waiting. We might be idle but have someone waiting if the device we @@ -621,9 +618,9 @@ BaseBus::Layer::drain(DrainManager *dm) return 0; } -template +template void -BaseBus::Layer::regStats() +BaseBus::Layer::regStats() { using namespace Stats; @@ -646,5 +643,5 @@ BaseBus::Layer::regStats() * file, but since there are only two given options (MasterPort and * SlavePort) it seems a bit excessive at this point. */ -template class BaseBus::Layer; -template class BaseBus::Layer; +template class BaseBus::Layer; +template class BaseBus::Layer; -- cgit v1.2.3