55 #include "debug/AddrRanges.hh" 56 #include "debug/CoherentXBar.hh" 61 snoopResponseLatency(p->snoop_response_latency),
62 maxOutstandingSnoopCheck(p->max_outstanding_snoops),
63 maxRoutingTableSizeCheck(p->max_routing_table_size),
64 pointOfCoherency(p->point_of_coherency),
65 pointOfUnification(p->point_of_unification),
67 snoops(this,
"snoops",
"Total snoops (count)"),
68 snoopTraffic(this,
"snoopTraffic",
"Total snoop traffic (bytes)"),
69 snoopFanout(this,
"snoop_fanout",
"Request fanout histogram")
74 for (
int i = 0;
i < p->port_master_connection_count; ++
i) {
86 if (p->port_default_connection_count) {
88 std::string portName =
name() +
".default";
100 for (
int i = 0;
i < p->port_slave_connection_count; ++
i) {
131 if (
p->isSnooping()) {
132 DPRINTF(AddrRanges,
"Adding snooping master %s\n",
p->getPeer());
138 warn(
"CoherentXBar %s has no snooping ports attached!\n",
name());
157 assert(is_express_snoop == cache_responding);
164 if (!is_express_snoop && !
reqLayers[master_port_id]->tryTiming(src_port)) {
201 if (pkt->
isClean() && !is_destination) {
205 if (!
masterPorts[master_port_id]->tryTiming(pkt)) {
210 reqLayers[master_port_id]->failedTiming(src_port,
227 __func__, src_port->
name(), pkt->
print(),
228 sf_res.first.size(), sf_res.second);
236 if (!sf_res.first.empty())
256 const bool expect_snoop_resp = !cache_responding && pkt->
cacheResponding();
262 bool respond_directly =
false;
285 if (pkt->
isWrite() && is_destination) {
290 success =
masterPorts[master_port_id]->sendTimingReq(pkt);
296 respond_directly =
true;
297 assert(!expect_snoop_resp);
298 expect_response =
false;
310 assert(!is_express_snoop);
319 reqLayers[master_port_id]->failedTiming(src_port,
323 if (!is_express_snoop) {
326 if (expect_snoop_resp) {
334 "%s: Outstanding snoop requests exceeded %d\n",
339 if (expect_response || expect_snoop_resp) {
344 "%s: Routing table exceeds %d packets\n",
349 reqLayers[master_port_id]->succeededTiming(packetFinishTime);
353 pktCount[slave_port_id][master_port_id]++;
354 pktSize[slave_port_id][master_port_id] += pkt_size;
357 if (is_express_snoop) {
369 PortID rsp_port_id = slave_port_id;
389 respond_directly =
true;
391 rsp_pkt = cmo_lookup->second;
395 const auto route_lookup =
routeTo.find(rsp_pkt->
req);
396 assert(route_lookup !=
routeTo.end());
397 rsp_port_id = route_lookup->second;
405 respond_directly =
false;
412 "%s: Routing table exceeds %d packets\n",
419 if (respond_directly) {
437 slavePorts[rsp_port_id]->schedTimingResp(rsp_pkt, response_time);
450 const auto route_lookup =
routeTo.find(pkt->
req);
451 assert(route_lookup !=
routeTo.end());
452 const PortID slave_port_id = route_lookup->second;
458 if (!
respLayers[slave_port_id]->tryTiming(src_port)) {
495 respLayers[slave_port_id]->succeededTiming(packetFinishTime);
498 pktCount[slave_port_id][master_port_id]++;
499 pktSize[slave_port_id][master_port_id] += pkt_size;
539 sf_res.first.size(), sf_res.second);
572 const auto route_lookup =
routeTo.find(pkt->
req);
573 assert(route_lookup !=
routeTo.end());
574 const PortID dest_port_id = route_lookup->second;
588 if (forwardAsSnoop) {
590 if (!
snoopLayers[dest_port_id]->tryTiming(src_port)) {
599 if (!
respLayers[dest_port_id]->tryTiming(snoop_port)) {
630 if (forwardAsSnoop) {
642 masterPorts[dest_port_id]->sendTimingSnoopResp(pkt);
643 pktCount[slave_port_id][dest_port_id]++;
644 pktSize[slave_port_id][dest_port_id] += pkt_size;
647 snoopLayers[dest_port_id]->succeededTiming(packetFinishTime);
658 assert(slave_port_id != dest_port_id);
676 respLayers[dest_port_id]->succeededTiming(packetFinishTime);
702 for (
const auto&
p: dests) {
708 p->getId() != exclude_slave_port_id) {
710 p->sendTimingSnoopReq(pkt);
739 Tick snoop_response_latency = 0;
756 snoop_response_latency += sf_res.second *
clockPeriod();
759 sf_res.first.size(), sf_res.second);
773 if (!sf_res.first.empty())
782 snoop_response_cmd = snoop_result.first;
783 snoop_response_latency += snoop_result.second;
787 Tick response_latency = 0;
803 if (pkt->
isWrite() && is_destination) {
809 response_latency = backdoor ?
810 master->sendAtomicBackdoor(pkt, *backdoor) :
811 master->sendAtomic(pkt);
821 pktCount[slave_port_id][master_port_id]++;
822 pktSize[slave_port_id][master_port_id] += pkt_size;
835 pkt->
cmd = snoop_response_cmd;
836 response_latency = snoop_response_latency;
869 pktCount[slave_port_id][master_port_id]++;
870 pktSize[slave_port_id][master_port_id] += pkt_size;
876 return response_latency;
892 Tick snoop_response_latency = 0;
895 snoop_response_latency += sf_res.second *
clockPeriod();
898 sf_res.first.size(), sf_res.second);
904 MemCmd snoop_response_cmd = snoop_result.first;
905 snoop_response_latency += snoop_result.second;
908 pkt->
cmd = snoop_response_cmd;
917 return snoop_response_latency;
922 PortID source_master_port_id,
930 Tick snoop_response_latency = 0;
937 for (
const auto&
p: dests) {
943 p->getId() == exclude_slave_port_id)
946 Tick latency =
p->sendAtomicSnoop(pkt);
956 assert(pkt->
cmd != orig_cmd);
961 snoop_response_cmd = pkt->
cmd;
962 snoop_response_latency = latency;
988 return std::make_pair(snoop_response_cmd, snoop_response_latency);
1013 if (
p->trySatisfyFunctional(pkt)) {
1036 if (
p->trySatisfyFunctional(pkt)) {
1059 p->getId() != exclude_slave_port_id)
1060 p->sendFunctionalSnoop(pkt);
1117 CoherentXBarParams::create()
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
std::vector< SnoopRespLayer * > snoopLayers
void updateSnoopForward(const Packet *cpkt, const SlavePort &rsp_port, const MasterPort &req_port)
Pass snoop responses that travel downward through the snoop filter and let them update the snoop filt...
bool isExpressSnoop() const
Cycles is a wrapper class for representing cycle counts, i.e.
std::vector< RespLayer * > respLayers
const PortID InvalidPortID
void finishRequest(bool will_retry, Addr addr, bool is_secure)
For an un-successful request, revert the change to the snoop filter.
uint32_t snoopDelay
Keep track of the extra delay incurred by snooping upwards before sending a request down the memory s...
const unsigned int maxOutstandingSnoopCheck
Maximum number of outstading snoops sanity check.
bool isCleanEviction() const
Is this packet a clean eviction, including both actual clean evict packets, but also clean writebacks...
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
PortID defaultPortID
Port that handles requests that don't match any of the interfaces.
void setSlavePorts(const SnoopList &slave_ports)
Init a new snoop filter and tell it about all the slave ports of the enclosing bus.
void recvReqRetry(PortID master_port_id)
Stats::Distribution snoopFanout
std::unordered_map< RequestPtr, PortID > routeTo
Remember where request packets came from so that we can route responses to the appropriate port...
bool cacheResponding() const
Internal class to bridge between an incoming snoop response from a slave port and forwarding it throu...
const Cycles responseLatency
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
A SlavePort is a specialisation of a port.
std::vector< ReqLayer * > reqLayers
Declare the layers of this crossbar, one vector for requests, one for responses, and one for snoop re...
Stats::Scalar snoopTraffic
const Cycles snoopResponseLatency
Cycles of snoop response latency.
System * system
Keep a pointer to the system to be allow to querying memory system properties.
Declaration of the coherent crossbar slave port type, one will be instantiated for each of the master...
std::unordered_set< RequestPtr > outstandingSnoop
Store the outstanding requests that we are expecting snoop responses from so we can determine which s...
bool sinkPacket(const PacketPtr pkt) const
Determine if the crossbar should sink the packet, as opposed to forwarding it, or responding...
void recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving a functional snoop transaction.
bool recvTimingReq(PacketPtr pkt, PortID slave_port_id)
bool needsWritable() const
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
std::pair< SnoopList, Cycles > lookupSnoop(const Packet *cpkt)
Handle an incoming snoop from below (the master port).
RequestPtr req
A pointer to the original request.
void regStats() override
Callback to set stat parameters.
bool isBlockCached() const
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Tick curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
bool needsResponse() const
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
uint64_t Tick
Tick count type.
Stats::Vector transDist
Stats for transaction distribution and data passing through the crossbar.
bool isDestination(const PacketPtr pkt) const
Determine if the packet's destination is the memory below.
void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
const unsigned int maxRoutingTableSizeCheck
Maximum routing table size sanity check.
CoherentXBar(const CoherentXBarParams *p)
SnoopFilter * snoopFilter
A snoop filter that tracks cache line residency and can restrict the broadcast needed for probes...
AddrRange getAddrRange() const
Get address range to which this packet belongs.
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
bool recvTimingResp(PacketPtr pkt, PortID master_port_id)
void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
Forward a timing packet to our snoopers, potentially excluding one of the connected coherent masters ...
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
virtual const std::string name() const
A coherent crossbar connects a number of (potentially) snooping masters and slaves, and routes the request and response packets based on the address, and also forwards all requests to the snoopers and deals with the snoop responses.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
const Cycles frontendLatency
Cycles of front-end pipeline including the delay to accept the request and to decode the address...
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
void updateResponse(const Packet *cpkt, const SlavePort &slave_port)
Update the snoop filter with a response from below (outer / other cache, or memory) and update the tr...
bool responderHadWritable() const
Declaration of a coherent crossbar.
Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
int cmdToIndex() const
Return the index of this command.
std::vector< MasterPort * > masterPorts
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
std::vector< SnoopRespPort * > snoopRespPorts
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
MemCmd cmd
The command field of the packet.
bool bypassCaches() const
Should caches be bypassed?
const std::string name() const
Return port name (for DPRINTF).
PortID findPort(AddrRange addr_range)
Find which port connected to this crossbar (if any) should be given a packet with this address range...
void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
Forward a functional packet to our snoopers, potentially excluding one of the connected coherent mast...
std::pair< MemCmd, Tick > forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
Forward an atomic packet to our snoopers, potentially excluding one of the connected coherent masters...
virtual void regStats()
Callback to set stat parameters.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
const Cycles forwardLatency
void setExpressSnoop()
The express snoop flag is used for two purposes.
bool forwardPacket(const PacketPtr pkt)
Determine if the crossbar should forward the packet, as opposed to responding to it.
const bool pointOfCoherency
Is this crossbar the point of coherency?
void updateSnoopResponse(const Packet *cpkt, const SlavePort &rsp_port, const SlavePort &req_port)
Let the snoop filter see any snoop responses that turn into request responses and indicate cache to c...
static const int NumArgumentRegs M5_VAR_USED
bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
std::unordered_map< PacketId, PacketPtr > outstandingCMO
Store the outstanding cache maintenance that we are expecting snoop responses from so we can determin...
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
std::pair< SnoopList, Cycles > lookupRequest(const Packet *cpkt, const SlavePort &slave_port)
Lookup a request (from a slave port) in the snoop filter and return a list of other slave ports that ...
Declaration of the coherent crossbar master port type, one will be instantiated for each of the slave...
Tick recvAtomicBackdoor(PacketPtr pkt, PortID slave_port_id, MemBackdoorPtr *backdoor=nullptr)
void recvFunctional(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Functional transaction.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
std::vector< QueuedSlavePort * > snoopPorts