/*
- * Copyright (c) 2011-2018 ARM Limited
+ * Copyright (c) 2011-2020 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Ali Saidi
- * Andreas Hansson
- * William Wang
- * Nikos Nikoleris
*/
/**
#include "debug/CoherentXBar.hh"
#include "sim/system.hh"
-CoherentXBar::CoherentXBar(const CoherentXBarParams *p)
- : BaseXBar(p), system(p->system), snoopFilter(p->snoop_filter),
- snoopResponseLatency(p->snoop_response_latency),
- pointOfCoherency(p->point_of_coherency),
- pointOfUnification(p->point_of_unification)
+CoherentXBar::CoherentXBar(const CoherentXBarParams &p)
+ : BaseXBar(p), system(p.system), snoopFilter(p.snoop_filter),
+ snoopResponseLatency(p.snoop_response_latency),
+ maxOutstandingSnoopCheck(p.max_outstanding_snoops),
+ maxRoutingTableSizeCheck(p.max_routing_table_size),
+ pointOfCoherency(p.point_of_coherency),
+ pointOfUnification(p.point_of_unification),
+
+ ADD_STAT(snoops, UNIT_COUNT, "Total snoops"),
+ ADD_STAT(snoopTraffic, UNIT_BYTE, "Total snoop traffic"),
+ ADD_STAT(snoopFanout, UNIT_COUNT, "Request fanout histogram")
{
- // create the ports based on the size of the master and slave
- // vector ports, and the presence of the default port, the ports
- // are enumerated starting from zero
- for (int i = 0; i < p->port_master_connection_count; ++i) {
- std::string portName = csprintf("%s.master[%d]", name(), i);
- MasterPort* bp = new CoherentXBarMasterPort(portName, *this, i);
- masterPorts.push_back(bp);
+ // create the ports based on the size of the memory-side port and
+ // CPU-side port vector ports, and the presence of the default port,
+ // the ports are enumerated starting from zero
+ for (int i = 0; i < p.port_mem_side_ports_connection_count; ++i) {
+ std::string portName = csprintf("%s.mem_side_port[%d]", name(), i);
+ RequestPort* bp = new CoherentXBarRequestPort(portName, *this, i);
+ memSidePorts.push_back(bp);
reqLayers.push_back(new ReqLayer(*bp, *this,
- csprintf(".reqLayer%d", i)));
- snoopLayers.push_back(new SnoopRespLayer(*bp, *this,
- csprintf(".snoopLayer%d", i)));
+ csprintf("reqLayer%d", i)));
+ snoopLayers.push_back(
+ new SnoopRespLayer(*bp, *this, csprintf("snoopLayer%d", i)));
}
- // see if we have a default slave device connected and if so add
- // our corresponding master port
- if (p->port_default_connection_count) {
- defaultPortID = masterPorts.size();
+ // see if we have a default CPU-side-port device connected and if so add
+ // our corresponding memory-side port
+ if (p.port_default_connection_count) {
+ defaultPortID = memSidePorts.size();
std::string portName = name() + ".default";
- MasterPort* bp = new CoherentXBarMasterPort(portName, *this,
- defaultPortID);
- masterPorts.push_back(bp);
- reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
- defaultPortID)));
+ RequestPort* bp = new CoherentXBarRequestPort(portName, *this,
+ defaultPortID);
+ memSidePorts.push_back(bp);
+ reqLayers.push_back(new ReqLayer(*bp, *this, csprintf("reqLayer%d",
+ defaultPortID)));
snoopLayers.push_back(new SnoopRespLayer(*bp, *this,
- csprintf(".snoopLayer%d",
+ csprintf("snoopLayer%d",
defaultPortID)));
}
- // create the slave ports, once again starting at zero
- for (int i = 0; i < p->port_slave_connection_count; ++i) {
- std::string portName = csprintf("%s.slave[%d]", name(), i);
- QueuedSlavePort* bp = new CoherentXBarSlavePort(portName, *this, i);
- slavePorts.push_back(bp);
+ // create the CPU-side ports, once again starting at zero
+ for (int i = 0; i < p.port_cpu_side_ports_connection_count; ++i) {
+ std::string portName = csprintf("%s.cpu_side_port[%d]", name(), i);
+ QueuedResponsePort* bp = new CoherentXBarResponsePort(portName,
+ *this, i);
+ cpuSidePorts.push_back(bp);
respLayers.push_back(new RespLayer(*bp, *this,
- csprintf(".respLayer%d", i)));
+ csprintf("respLayer%d", i)));
snoopRespPorts.push_back(new SnoopRespPort(*bp, *this));
}
}
{
BaseXBar::init();
- // iterate over our slave ports and determine which of our
- // neighbouring master ports are snooping and add them as snoopers
- for (const auto& p: slavePorts) {
- // check if the connected master port is snooping
+ // iterate over our CPU-side ports and determine which of our
+ // neighbouring memory-side ports are snooping and add them as snoopers
+ for (const auto& p: cpuSidePorts) {
+ // check if the connected memory-side port is snooping
if (p->isSnooping()) {
- DPRINTF(AddrRanges, "Adding snooping master %s\n",
- p->getMasterPort().name());
+ DPRINTF(AddrRanges, "Adding snooping requestor %s\n",
+ p->getPeer());
snoopPorts.push_back(p);
}
}
if (snoopPorts.empty())
warn("CoherentXBar %s has no snooping ports attached!\n", name());
- // inform the snoop filter about the slave ports so it can create
+ // inform the snoop filter about the CPU-side ports so it can create
// its own internal representation
if (snoopFilter)
- snoopFilter->setSlavePorts(slavePorts);
+ snoopFilter->setCPUSidePorts(cpuSidePorts);
}
bool
-CoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
+CoherentXBar::recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id)
{
// determine the source port based on the id
- SlavePort *src_port = slavePorts[slave_port_id];
+ ResponsePort *src_port = cpuSidePorts[cpu_side_port_id];
// remember if the packet is an express snoop
bool is_express_snoop = pkt->isExpressSnoop();
assert(is_express_snoop == cache_responding);
// determine the destination based on the destination address range
- AddrRange addr_range = RangeSize(pkt->getAddr(), pkt->getSize());
- PortID master_port_id = findPort(addr_range);
+ PortID mem_side_port_id = findPort(pkt->getAddrRange());
// test if the crossbar should be considered occupied for the current
// port, and exclude express snoops from the check
- if (!is_express_snoop && !reqLayers[master_port_id]->tryTiming(src_port)) {
+ if (!is_express_snoop &&
+ !reqLayers[mem_side_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
src_port->name(), pkt->print());
return false;
calcPacketTiming(pkt, xbar_delay);
// determine how long to be crossbar layer is busy
- Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
+ Tick packetFinishTime = clockEdge(headerLatency) + pkt->payloadDelay;
// is this the destination point for this packet? (e.g. true if
// this xbar is the PoC for a cache maintenance operation to the
// before snooping we need to make sure that the memory
// below is not busy and the cache clean request can be
// forwarded to it
- if (!masterPorts[master_port_id]->tryTiming(pkt)) {
+ if (!memSidePorts[mem_side_port_id]->tryTiming(pkt)) {
DPRINTF(CoherentXBar, "%s: src %s packet %s RETRY\n", __func__,
src_port->name(), pkt->print());
// update the layer state and schedule an idle event
- reqLayers[master_port_id]->failedTiming(src_port,
+ reqLayers[mem_side_port_id]->failedTiming(src_port,
clockEdge(Cycles(1)));
return false;
}
if (!sf_res.first.empty())
pkt->setBlockCached();
} else {
- forwardTiming(pkt, slave_port_id, sf_res.first);
+ forwardTiming(pkt, cpu_side_port_id, sf_res.first);
}
} else {
- forwardTiming(pkt, slave_port_id);
+ forwardTiming(pkt, cpu_side_port_id);
}
// add the snoop delay to our header delay, and then reset it
}
// since it is a normal request, attempt to send the packet
- success = masterPorts[master_port_id]->sendTimingReq(pkt);
+ success = memSidePorts[mem_side_port_id]->sendTimingReq(pkt);
} else {
// no need to forward, turn this packet around and respond
// directly
src_port->name(), pkt->print());
// update the layer state and schedule an idle event
- reqLayers[master_port_id]->failedTiming(src_port,
+ reqLayers[mem_side_port_id]->failedTiming(src_port,
clockEdge(Cycles(1)));
} else {
// express snoops currently bypass the crossbar state entirely
outstandingSnoop.insert(pkt->req);
// basic sanity check on the outstanding snoops
- panic_if(outstandingSnoop.size() > 512,
- "Outstanding snoop requests exceeded 512\n");
+ panic_if(outstandingSnoop.size() > maxOutstandingSnoopCheck,
+ "%s: Outstanding snoop requests exceeded %d\n",
+ name(), maxOutstandingSnoopCheck);
}
// remember where to route the normal response to
if (expect_response || expect_snoop_resp) {
assert(routeTo.find(pkt->req) == routeTo.end());
- routeTo[pkt->req] = slave_port_id;
+ routeTo[pkt->req] = cpu_side_port_id;
- panic_if(routeTo.size() > 512,
- "Routing table exceeds 512 packets\n");
+ panic_if(routeTo.size() > maxRoutingTableSizeCheck,
+ "%s: Routing table exceeds %d packets\n",
+ name(), maxRoutingTableSizeCheck);
}
// update the layer state and schedule an idle event
- reqLayers[master_port_id]->succeededTiming(packetFinishTime);
+ reqLayers[mem_side_port_id]->succeededTiming(packetFinishTime);
}
// stats updates only consider packets that were successfully sent
- pktCount[slave_port_id][master_port_id]++;
- pktSize[slave_port_id][master_port_id] += pkt_size;
+ pktCount[cpu_side_port_id][mem_side_port_id]++;
+ pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
transDist[pkt_cmd]++;
if (is_express_snoop) {
// normally we respond to the packet we just received if we need to
PacketPtr rsp_pkt = pkt;
- PortID rsp_port_id = slave_port_id;
+ PortID rsp_port_id = cpu_side_port_id;
// If this is the destination of the cache clean operation the
// crossbar is responsible for responding. This crossbar will
outstandingCMO.emplace(pkt->id, deferred_rsp);
if (!pkt->isWrite()) {
assert(routeTo.find(pkt->req) == routeTo.end());
- routeTo[pkt->req] = slave_port_id;
+ routeTo[pkt->req] = cpu_side_port_id;
- panic_if(routeTo.size() > 512,
- "Routing table exceeds 512 packets\n");
+ panic_if(routeTo.size() > maxRoutingTableSizeCheck,
+ "%s: Routing table exceeds %d packets\n",
+ name(), maxRoutingTableSizeCheck);
}
}
}
if (snoopFilter && !system->bypassCaches()) {
// let the snoop filter inspect the response and update its state
- snoopFilter->updateResponse(rsp_pkt, *slavePorts[rsp_port_id]);
+ snoopFilter->updateResponse(rsp_pkt, *cpuSidePorts[rsp_port_id]);
}
// we send the response after the current packet, even if the
Tick response_time = clockEdge() + pkt->headerDelay;
rsp_pkt->headerDelay = 0;
- slavePorts[rsp_port_id]->schedTimingResp(rsp_pkt, response_time);
+ cpuSidePorts[rsp_port_id]->schedTimingResp(rsp_pkt, response_time);
}
return success;
}
bool
-CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
+CoherentXBar::recvTimingResp(PacketPtr pkt, PortID mem_side_port_id)
{
// determine the source port based on the id
- MasterPort *src_port = masterPorts[master_port_id];
+ RequestPort *src_port = memSidePorts[mem_side_port_id];
// determine the destination
const auto route_lookup = routeTo.find(pkt->req);
assert(route_lookup != routeTo.end());
- const PortID slave_port_id = route_lookup->second;
- assert(slave_port_id != InvalidPortID);
- assert(slave_port_id < respLayers.size());
+ const PortID cpu_side_port_id = route_lookup->second;
+ assert(cpu_side_port_id != InvalidPortID);
+ assert(cpu_side_port_id < respLayers.size());
// test if the crossbar should be considered occupied for the
// current port
- if (!respLayers[slave_port_id]->tryTiming(src_port)) {
+ if (!respLayers[cpu_side_port_id]->tryTiming(src_port)) {
DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
src_port->name(), pkt->print());
return false;
calcPacketTiming(pkt, xbar_delay);
// determine how long to be crossbar layer is busy
- Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
+ Tick packetFinishTime = clockEdge(headerLatency) + pkt->payloadDelay;
if (snoopFilter && !system->bypassCaches()) {
// let the snoop filter inspect the response and update its state
- snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]);
+ snoopFilter->updateResponse(pkt, *cpuSidePorts[cpu_side_port_id]);
}
- // send the packet through the destination slave port and pay for
+ // send the packet through the destination CPU-side port and pay for
// any outstanding header delay
Tick latency = pkt->headerDelay;
pkt->headerDelay = 0;
- slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency);
+ cpuSidePorts[cpu_side_port_id]->schedTimingResp(pkt, curTick()
+ + latency);
// remove the request from the routing table
routeTo.erase(route_lookup);
- respLayers[slave_port_id]->succeededTiming(packetFinishTime);
+ respLayers[cpu_side_port_id]->succeededTiming(packetFinishTime);
// stats updates
- pktCount[slave_port_id][master_port_id]++;
- pktSize[slave_port_id][master_port_id] += pkt_size;
+ pktCount[cpu_side_port_id][mem_side_port_id]++;
+ pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
transDist[pkt_cmd]++;
return true;
}
void
-CoherentXBar::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
+CoherentXBar::recvTimingSnoopReq(PacketPtr pkt, PortID mem_side_port_id)
{
DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
- masterPorts[master_port_id]->name(), pkt->print());
+ memSidePorts[mem_side_port_id]->name(), pkt->print());
// update stats here as we know the forwarding will succeed
unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
// of the snoop filter
pkt->headerDelay += sf_res.second * clockPeriod();
DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
- __func__, masterPorts[master_port_id]->name(), pkt->print(),
- sf_res.first.size(), sf_res.second);
+ __func__, memSidePorts[mem_side_port_id]->name(),
+ pkt->print(), sf_res.first.size(), sf_res.second);
// forward to all snoopers
forwardTiming(pkt, InvalidPortID, sf_res.first);
// if we can expect a response, remember how to route it
if (!cache_responding && pkt->cacheResponding()) {
assert(routeTo.find(pkt->req) == routeTo.end());
- routeTo[pkt->req] = master_port_id;
+ routeTo[pkt->req] = mem_side_port_id;
}
- // a snoop request came from a connected slave device (one of
- // our master ports), and if it is not coming from the slave
+ // a snoop request came from a connected CPU-side-port device (one of
+ // our memory-side ports), and if it is not coming from the CPU-side-port
// device responsible for the address range something is
// wrong, hence there is nothing further to do as the packet
// would be going back to where it came from
- AddrRange addr_range M5_VAR_USED =
- RangeSize(pkt->getAddr(), pkt->getSize());
- assert(findPort(addr_range) == master_port_id);
+ assert(findPort(pkt->getAddrRange()) == mem_side_port_id);
}
bool
-CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
+CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID cpu_side_port_id)
{
// determine the source port based on the id
- SlavePort* src_port = slavePorts[slave_port_id];
+ ResponsePort* src_port = cpuSidePorts[cpu_side_port_id];
// get the destination
const auto route_lookup = routeTo.find(pkt->req);
return false;
}
} else {
- // get the master port that mirrors this slave port internally
- MasterPort* snoop_port = snoopRespPorts[slave_port_id];
+ // get the memory-side port that mirrors this CPU-side port internally
+ RequestPort* snoop_port = snoopRespPorts[cpu_side_port_id];
assert(dest_port_id < respLayers.size());
if (!respLayers[dest_port_id]->tryTiming(snoop_port)) {
DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
calcPacketTiming(pkt, xbar_delay);
// determine how long to be crossbar layer is busy
- Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
+ Tick packetFinishTime = clockEdge(headerLatency) + pkt->payloadDelay;
// forward it either as a snoop response or a normal response
if (forwardAsSnoop) {
if (snoopFilter) {
// update the probe filter so that it can properly track the line
- snoopFilter->updateSnoopForward(pkt, *slavePorts[slave_port_id],
- *masterPorts[dest_port_id]);
+ snoopFilter->updateSnoopForward(pkt,
+ *cpuSidePorts[cpu_side_port_id],
+ *memSidePorts[dest_port_id]);
}
- bool success M5_VAR_USED =
- masterPorts[dest_port_id]->sendTimingSnoopResp(pkt);
- pktCount[slave_port_id][dest_port_id]++;
- pktSize[slave_port_id][dest_port_id] += pkt_size;
+ M5_VAR_USED bool success =
+ memSidePorts[dest_port_id]->sendTimingSnoopResp(pkt);
+ pktCount[cpu_side_port_id][dest_port_id]++;
+ pktSize[cpu_side_port_id][dest_port_id] += pkt_size;
assert(success);
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 crossbar, and
+ // we got a snoop response on one of our CPU-side ports,
+ // i.e. from a coherent requestor connected to the crossbar, and
// since we created the snoop request as part of recvTiming,
// this should now be a normal response again
outstandingSnoop.erase(pkt->req);
- // this is a snoop response from a coherent master, hence it
+ // this is a snoop response from a coherent requestor, hence it
// should never go back to where the snoop response came from,
// but instead to where the original request came from
- assert(slave_port_id != dest_port_id);
+ assert(cpu_side_port_id != dest_port_id);
if (snoopFilter) {
- // update the probe filter so that it can properly track the line
- snoopFilter->updateSnoopResponse(pkt, *slavePorts[slave_port_id],
- *slavePorts[dest_port_id]);
+ // update the probe filter so that it can properly track
+ // the line
+ snoopFilter->updateSnoopResponse(pkt,
+ *cpuSidePorts[cpu_side_port_id],
+ *cpuSidePorts[dest_port_id]);
}
DPRINTF(CoherentXBar, "%s: src %s packet %s FWD RESP\n", __func__,
src_port->name(), pkt->print());
- // as a normal response, it should go back to a master through
- // one of our slave ports, we also pay for any outstanding
+ // as a normal response, it should go back to a requestor through
+ // one of our CPU-side ports, we also pay for any outstanding
// header latency
Tick latency = pkt->headerDelay;
pkt->headerDelay = 0;
- slavePorts[dest_port_id]->schedTimingResp(pkt, curTick() + latency);
+ cpuSidePorts[dest_port_id]->schedTimingResp(pkt,
+ curTick() + latency);
respLayers[dest_port_id]->succeededTiming(packetFinishTime);
}
void
-CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
- const std::vector<QueuedSlavePort*>& dests)
+CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_cpu_side_port_id,
+ const std::vector<QueuedResponsePort*>& dests)
{
DPRINTF(CoherentXBar, "%s for %s\n", __func__, pkt->print());
unsigned fanout = 0;
for (const auto& p: dests) {
- // we could have gotten this request from a snooping master
- // (corresponding to our own slave port that is also in
+ // we could have gotten this request from a snooping requestor
+ // (corresponding to our own CPU-side port that is also in
// snoopPorts) and should not send it back to where it came
// from
- if (exclude_slave_port_id == InvalidPortID ||
- p->getId() != exclude_slave_port_id) {
+ if (exclude_cpu_side_port_id == InvalidPortID ||
+ p->getId() != exclude_cpu_side_port_id) {
// cache is not allowed to refuse snoop
p->sendTimingSnoopReq(pkt);
fanout++;
}
void
-CoherentXBar::recvReqRetry(PortID master_port_id)
+CoherentXBar::recvReqRetry(PortID mem_side_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
- reqLayers[master_port_id]->recvRetry();
+ reqLayers[mem_side_port_id]->recvRetry();
}
Tick
-CoherentXBar::recvAtomic(PacketPtr pkt, PortID slave_port_id)
+CoherentXBar::recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id,
+ MemBackdoorPtr *backdoor)
{
DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
- slavePorts[slave_port_id]->name(), pkt->print());
+ cpuSidePorts[cpu_side_port_id]->name(), pkt->print());
unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
unsigned int pkt_cmd = pkt->cmdToIndex();
if (snoopFilter) {
// check with the snoop filter where to forward this packet
auto sf_res =
- snoopFilter->lookupRequest(pkt, *slavePorts[slave_port_id]);
+ snoopFilter->lookupRequest(pkt,
+ *cpuSidePorts [cpu_side_port_id]);
snoop_response_latency += sf_res.second * clockPeriod();
DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
- __func__, slavePorts[slave_port_id]->name(), pkt->print(),
- sf_res.first.size(), sf_res.second);
+ __func__, cpuSidePorts[cpu_side_port_id]->name(),
+ pkt->print(), sf_res.first.size(), sf_res.second);
// let the snoop filter know about the success of the send
// operation, and do it even before sending it onwards to
if (!sf_res.first.empty())
pkt->setBlockCached();
} else {
- snoop_result = forwardAtomic(pkt, slave_port_id, InvalidPortID,
- sf_res.first);
+ snoop_result = forwardAtomic(pkt, cpu_side_port_id,
+ InvalidPortID, sf_res.first);
}
} else {
- snoop_result = forwardAtomic(pkt, slave_port_id);
+ snoop_result = forwardAtomic(pkt, cpu_side_port_id);
}
snoop_response_cmd = snoop_result.first;
snoop_response_latency += snoop_result.second;
// even if we had a snoop response, we must continue and also
// perform the actual request at the destination
- AddrRange addr_range = RangeSize(pkt->getAddr(), pkt->getSize());
- PortID master_port_id = findPort(addr_range);
+ PortID mem_side_port_id = findPort(pkt->getAddrRange());
if (sink_packet) {
DPRINTF(CoherentXBar, "%s: Not forwarding %s\n", __func__,
}
// forward the request to the appropriate destination
- response_latency = masterPorts[master_port_id]->sendAtomic(pkt);
+ auto mem_side_port = memSidePorts[mem_side_port_id];
+ response_latency = backdoor ?
+ mem_side_port->sendAtomicBackdoor(pkt, *backdoor) :
+ mem_side_port->sendAtomic(pkt);
} else {
// if it does not need a response we sink the packet above
assert(pkt->needsResponse());
}
// stats updates for the request
- pktCount[slave_port_id][master_port_id]++;
- pktSize[slave_port_id][master_port_id] += pkt_size;
+ pktCount[cpu_side_port_id][mem_side_port_id]++;
+ pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
transDist[pkt_cmd]++;
// if lower levels have replied, tell the snoop filter
if (!system->bypassCaches() && snoopFilter && pkt->isResponse()) {
- snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]);
+ snoopFilter->updateResponse(pkt, *cpuSidePorts[cpu_side_port_id]);
}
// if we got a response from a snooper, restore it here
// if this is the destination of the operation, the xbar
// sends the responce to the cache clean operation only
// after having encountered the cache clean request
- auto M5_VAR_USED ret = outstandingCMO.emplace(pkt->id, nullptr);
+ M5_VAR_USED auto ret = outstandingCMO.emplace(pkt->id, nullptr);
// in atomic mode we know that the WriteClean packet should
// precede the clean request
assert(ret.second);
pkt_cmd = pkt->cmdToIndex();
// stats updates
- pktCount[slave_port_id][master_port_id]++;
- pktSize[slave_port_id][master_port_id] += pkt_size;
+ pktCount[cpu_side_port_id][mem_side_port_id]++;
+ pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
transDist[pkt_cmd]++;
}
}
Tick
-CoherentXBar::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
+CoherentXBar::recvAtomicSnoop(PacketPtr pkt, PortID mem_side_port_id)
{
DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
- masterPorts[master_port_id]->name(), pkt->print());
+ memSidePorts[mem_side_port_id]->name(), pkt->print());
// add the request snoop data
unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
auto sf_res = snoopFilter->lookupSnoop(pkt);
snoop_response_latency += sf_res.second * clockPeriod();
DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
- __func__, masterPorts[master_port_id]->name(), pkt->print(),
- sf_res.first.size(), sf_res.second);
- snoop_result = forwardAtomic(pkt, InvalidPortID, master_port_id,
+ __func__, memSidePorts[mem_side_port_id]->name(),
+ pkt->print(), sf_res.first.size(), sf_res.second);
+ snoop_result = forwardAtomic(pkt, InvalidPortID, mem_side_port_id,
sf_res.first);
} else {
snoop_result = forwardAtomic(pkt, InvalidPortID);
}
std::pair<MemCmd, Tick>
-CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
- PortID source_master_port_id,
- const std::vector<QueuedSlavePort*>& dests)
+CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_cpu_side_port_id,
+ PortID source_mem_side_port_id,
+ const std::vector<QueuedResponsePort*>& dests)
{
// the packet may be changed on snoops, record the original
// command to enable us to restore it between snoops so that
unsigned fanout = 0;
for (const auto& p: dests) {
- // we could have gotten this request from a snooping master
- // (corresponding to our own slave port that is also in
+ // we could have gotten this request from a snooping memory-side port
+ // (corresponding to our own CPU-side port that is also in
// snoopPorts) and should not send it back to where it came
// from
- if (exclude_slave_port_id != InvalidPortID &&
- p->getId() == exclude_slave_port_id)
+ if (exclude_cpu_side_port_id != InvalidPortID &&
+ p->getId() == exclude_cpu_side_port_id)
continue;
Tick latency = p->sendAtomicSnoop(pkt);
if (snoopFilter) {
// Handle responses by the snoopers and differentiate between
// responses to requests from above and snoops from below
- if (source_master_port_id != InvalidPortID) {
+ if (source_mem_side_port_id != InvalidPortID) {
// Getting a response for a snoop from below
- assert(exclude_slave_port_id == InvalidPortID);
+ assert(exclude_cpu_side_port_id == InvalidPortID);
snoopFilter->updateSnoopForward(pkt, *p,
- *masterPorts[source_master_port_id]);
+ *memSidePorts[source_mem_side_port_id]);
} else {
// Getting a response for a request from above
- assert(source_master_port_id == InvalidPortID);
+ assert(source_mem_side_port_id == InvalidPortID);
snoopFilter->updateSnoopResponse(pkt, *p,
- *slavePorts[exclude_slave_port_id]);
+ *cpuSidePorts[exclude_cpu_side_port_id]);
}
}
// restore original packet state for remaining snoopers
}
void
-CoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id)
+CoherentXBar::recvFunctional(PacketPtr pkt, PortID cpu_side_port_id)
{
if (!pkt->isPrint()) {
// don't do DPRINTFs on PrintReq as it clutters up the output
DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
- slavePorts[slave_port_id]->name(), pkt->print());
+ cpuSidePorts[cpu_side_port_id]->name(), pkt->print());
}
if (!system->bypassCaches()) {
// forward to all snoopers but the source
- forwardFunctional(pkt, slave_port_id);
+ forwardFunctional(pkt, cpu_side_port_id);
}
// there is no need to continue if the snooping has found what we
// were looking for and the packet is already a response
if (!pkt->isResponse()) {
- // since our slave ports are queued ports we need to check them as well
- for (const auto& p : slavePorts) {
+ // since our CPU-side ports are queued ports we need to check
+ // them as well
+ for (const auto& p : cpuSidePorts) {
// if we find a response that has the data, then the
// downstream caches/memories may be out of date, so simply stop
// here
- if (p->checkFunctional(pkt)) {
+ if (p->trySatisfyFunctional(pkt)) {
if (pkt->needsResponse())
pkt->makeResponse();
return;
}
}
- PortID dest_id = findPort(RangeSize(pkt->getAddr(), pkt->getSize()));
+ PortID dest_id = findPort(pkt->getAddrRange());
- masterPorts[dest_id]->sendFunctional(pkt);
+ memSidePorts[dest_id]->sendFunctional(pkt);
}
}
void
-CoherentXBar::recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
+CoherentXBar::recvFunctionalSnoop(PacketPtr pkt, PortID mem_side_port_id)
{
if (!pkt->isPrint()) {
// don't do DPRINTFs on PrintReq as it clutters up the output
DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
- masterPorts[master_port_id]->name(), pkt->print());
+ memSidePorts[mem_side_port_id]->name(), pkt->print());
}
- for (const auto& p : slavePorts) {
- if (p->checkFunctional(pkt)) {
+ for (const auto& p : cpuSidePorts) {
+ if (p->trySatisfyFunctional(pkt)) {
if (pkt->needsResponse())
pkt->makeResponse();
return;
}
void
-CoherentXBar::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
+CoherentXBar::forwardFunctional(PacketPtr pkt, PortID exclude_cpu_side_port_id)
{
// snoops should only happen if the system isn't bypassing caches
assert(!system->bypassCaches());
for (const auto& p: snoopPorts) {
- // we could have gotten this request from a snooping master
- // (corresponding to our own slave port that is also in
+ // we could have gotten this request from a snooping requestor
+ // (corresponding to our own CPU-side port that is also in
// snoopPorts) and should not send it back to where it came
// from
- if (exclude_slave_port_id == InvalidPortID ||
- p->getId() != exclude_slave_port_id)
+ if (exclude_cpu_side_port_id == InvalidPortID ||
+ p->getId() != exclude_cpu_side_port_id)
p->sendFunctionalSnoop(pkt);
// if we get a response we are done
void
CoherentXBar::regStats()
{
- // register the stats of the base class and our layers
BaseXBar::regStats();
- for (auto l: reqLayers)
- l->regStats();
- for (auto l: respLayers)
- l->regStats();
- for (auto l: snoopLayers)
- l->regStats();
-
- snoops
- .name(name() + ".snoops")
- .desc("Total snoops (count)")
- ;
-
- snoopTraffic
- .name(name() + ".snoopTraffic")
- .desc("Total snoop traffic (bytes)")
- ;
-
- snoopFanout
- .init(0, snoopPorts.size(), 1)
- .name(name() + ".snoop_fanout")
- .desc("Request fanout histogram")
- ;
-}
-CoherentXBar *
-CoherentXBarParams::create()
-{
- return new CoherentXBar(this);
+ snoopFanout.init(0, snoopPorts.size(), 1);
}