summaryrefslogtreecommitdiff
path: root/src/mem/bus.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2012-07-09 12:35:37 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2012-07-09 12:35:37 -0400
commit8caaac048ae49310b905e190b20459232ae7aa9d (patch)
treec46f4657b287505ae3fa89eda6c1bf43c4efc3c2 /src/mem/bus.cc
parent995e6e4670f52c52f798320055d74994e6539cda (diff)
downloadgem5-8caaac048ae49310b905e190b20459232ae7aa9d.tar.xz
Bus: Split the bus into separate request/response layers
This patch splits the existing buses into multiple layers. The non-coherent bus is split into a request and a response layer, and the coherent bus adds an additional layer for the snoop responses. The layer is modified to be templatised on the port type, such that the different layers can have retryLists with either master or slave ports. This patch also removes the dynamic cast from the retry, as previously promised when moving the recvRetry from the port base class to the master/slave port respectively. Overall, the split bus more closely reflects any modern on-chip bus and should be at step in the right direction. From this point, it would be reasonable straight forward to add separate layers (and thus contention points and arbitration) for each port and thus create a true crossbar. The regressions all produce the correct output, but have varying degrees of changes to their statistics. A separate patch will be pushed with the updates to the reference statistics.
Diffstat (limited to 'src/mem/bus.cc')
-rw-r--r--src/mem/bus.cc42
1 files changed, 28 insertions, 14 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 16b581a7e..ab8b76594 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -137,13 +137,16 @@ BaseBus::calcPacketTiming(PacketPtr pkt)
return headerTime;
}
-BaseBus::Layer::Layer(BaseBus& _bus, const std::string& _name, Tick _clock) :
+template <typename PortClass>
+BaseBus::Layer<PortClass>::Layer(BaseBus& _bus, const std::string& _name,
+ Tick _clock) :
bus(_bus), _name(_name), state(IDLE), clock(_clock), drainEvent(NULL),
releaseEvent(this)
{
}
-void BaseBus::Layer::occupyLayer(Tick until)
+template <typename PortClass>
+void BaseBus::Layer<PortClass>::occupyLayer(Tick until)
{
// ensure the state is busy or in retry and never idle at this
// point, as the bus should transition from idle as soon as it has
@@ -164,8 +167,9 @@ void BaseBus::Layer::occupyLayer(Tick until)
curTick(), until);
}
+template <typename PortClass>
bool
-BaseBus::Layer::tryTiming(Port* port)
+BaseBus::Layer<PortClass>::tryTiming(PortClass* port)
{
// first we see if the bus is busy, next we check if we are in a
// retry with a port other than the current one
@@ -184,8 +188,9 @@ BaseBus::Layer::tryTiming(Port* port)
return true;
}
+template <typename PortClass>
void
-BaseBus::Layer::succeededTiming(Tick busy_time)
+BaseBus::Layer<PortClass>::succeededTiming(Tick busy_time)
{
// if a retrying port succeeded, also take it off the retry list
if (state == RETRY) {
@@ -203,8 +208,9 @@ BaseBus::Layer::succeededTiming(Tick busy_time)
occupyLayer(busy_time);
}
+template <typename PortClass>
void
-BaseBus::Layer::failedTiming(SlavePort* port, Tick busy_time)
+BaseBus::Layer<PortClass>::failedTiming(PortClass* port, Tick busy_time)
{
// if we are not in a retry, i.e. busy (but never idle), or we are
// in a retry but not for the current port, then add the port at
@@ -221,8 +227,9 @@ BaseBus::Layer::failedTiming(SlavePort* port, Tick busy_time)
occupyLayer(busy_time);
}
+template <typename PortClass>
void
-BaseBus::Layer::releaseLayer()
+BaseBus::Layer<PortClass>::releaseLayer()
{
// releasing the bus means we should now be idle
assert(state == BUSY);
@@ -246,8 +253,9 @@ BaseBus::Layer::releaseLayer()
}
}
+template <typename PortClass>
void
-BaseBus::Layer::retryWaiting()
+BaseBus::Layer<PortClass>::retryWaiting()
{
// this should never be called with an empty retry list
assert(!retryList.empty());
@@ -262,10 +270,7 @@ BaseBus::Layer::retryWaiting()
// note that we might have blocked on the receiving port being
// busy (rather than the bus itself) and now call retry before the
// destination called retry on the bus
- if (dynamic_cast<SlavePort*>(retryList.front()) != NULL)
- (dynamic_cast<SlavePort*>(retryList.front()))->sendRetry();
- else
- (dynamic_cast<MasterPort*>(retryList.front()))->sendRetry();
+ retryList.front()->sendRetry();
// If the bus is still in the retry state, sendTiming wasn't
// called in zero time (e.g. the cache does this)
@@ -286,8 +291,9 @@ BaseBus::Layer::retryWaiting()
}
}
+template <typename PortClass>
void
-BaseBus::Layer::recvRetry()
+BaseBus::Layer<PortClass>::recvRetry()
{
// we got a retry from a peer that we tried to send something to
// and failed, but we sent it on the account of someone else, and
@@ -484,9 +490,9 @@ BaseBus::findBlockSize()
return max_bs;
}
-
+template <typename PortClass>
unsigned int
-BaseBus::Layer::drain(Event * de)
+BaseBus::Layer<PortClass>::drain(Event * de)
{
//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
@@ -497,3 +503,11 @@ BaseBus::Layer::drain(Event * de)
}
return 0;
}
+
+/**
+ * Bus layer template instantiations. Could be removed with _impl.hh
+ * file, but since there are only two given options (MasterPort and
+ * SlavePort) it seems a bit excessive at this point.
+ */
+template class BaseBus::Layer<SlavePort>;
+template class BaseBus::Layer<MasterPort>;