54 #include "debug/AddrRanges.hh"
55 #include "debug/CoherentXBar.hh"
60 snoopResponseLatency(p->snoop_response_latency),
61 pointOfCoherency(p->point_of_coherency)
66 for (
int i = 0;
i < p->port_master_connection_count; ++
i) {
78 if (p->port_default_connection_count) {
80 std::string portName =
name() +
".default";
92 for (
int i = 0;
i < p->port_slave_connection_count; ++
i) {
125 if (
p->isSnooping()) {
126 DPRINTF(AddrRanges,
"Adding snooping master %s\n",
127 p->getMasterPort().name());
133 warn(
"CoherentXBar %s has no snooping ports attached!\n",
name());
152 assert(is_express_snoop == cache_responding);
159 if (!is_express_snoop && !
reqLayers[master_port_id]->tryTiming(src_port)) {
198 __func__, src_port->
name(), pkt->
print(),
199 sf_res.first.size(), sf_res.second);
207 if (!sf_res.first.empty())
227 const bool expect_snoop_resp = !cache_responding && pkt->
cacheResponding();
233 bool respond_directly =
false;
254 success =
masterPorts[master_port_id]->sendTimingReq(pkt);
260 respond_directly =
true;
261 assert(!expect_snoop_resp);
262 expect_response =
false;
274 assert(!is_express_snoop);
283 reqLayers[master_port_id]->failedTiming(src_port,
287 if (!is_express_snoop) {
290 if (expect_snoop_resp) {
298 "Outstanding snoop requests exceeded 512\n");
302 if (expect_response || expect_snoop_resp) {
307 "Routing table exceeds 512 packets\n");
311 reqLayers[master_port_id]->succeededTiming(packetFinishTime);
315 pktCount[slave_port_id][master_port_id]++;
316 pktSize[slave_port_id][master_port_id] += pkt_size;
319 if (is_express_snoop) {
329 if (respond_directly) {
343 slavePorts[slave_port_id]->schedTimingResp(pkt, response_time);
356 const auto route_lookup =
routeTo.find(pkt->
req);
357 assert(route_lookup !=
routeTo.end());
358 const PortID slave_port_id = route_lookup->second;
364 if (!
respLayers[slave_port_id]->tryTiming(src_port)) {
401 respLayers[slave_port_id]->succeededTiming(packetFinishTime);
404 pktCount[slave_port_id][master_port_id]++;
405 pktSize[slave_port_id][master_port_id] += pkt_size;
445 sf_res.first.size(), sf_res.second);
478 const auto route_lookup =
routeTo.find(pkt->
req);
479 assert(route_lookup !=
routeTo.end());
480 const PortID dest_port_id = route_lookup->second;
494 if (forwardAsSnoop) {
496 if (!
snoopLayers[dest_port_id]->tryTiming(src_port)) {
505 if (!
respLayers[dest_port_id]->tryTiming(snoop_port)) {
536 if (forwardAsSnoop) {
548 masterPorts[dest_port_id]->sendTimingSnoopResp(pkt);
549 pktCount[slave_port_id][dest_port_id]++;
550 pktSize[slave_port_id][dest_port_id] += pkt_size;
553 snoopLayers[dest_port_id]->succeededTiming(packetFinishTime);
564 assert(slave_port_id != dest_port_id);
582 respLayers[dest_port_id]->succeededTiming(packetFinishTime);
608 for (
const auto&
p: dests) {
614 p->getId() != exclude_slave_port_id) {
616 p->sendTimingSnoopReq(pkt);
644 Tick snoop_response_latency = 0;
653 snoop_response_latency += sf_res.second *
clockPeriod();
656 sf_res.first.size(), sf_res.second);
669 snoop_response_cmd = snoop_result.first;
670 snoop_response_latency += snoop_result.second;
674 Tick response_latency = 0;
688 response_latency =
masterPorts[master_port_id]->sendAtomic(pkt);
698 pktCount[slave_port_id][master_port_id]++;
699 pktSize[slave_port_id][master_port_id] += pkt_size;
712 pkt->
cmd = snoop_response_cmd;
713 response_latency = snoop_response_latency;
722 pktCount[slave_port_id][master_port_id]++;
723 pktSize[slave_port_id][master_port_id] += pkt_size;
729 return response_latency;
745 Tick snoop_response_latency = 0;
748 snoop_response_latency += sf_res.second *
clockPeriod();
751 sf_res.first.size(), sf_res.second);
757 MemCmd snoop_response_cmd = snoop_result.first;
758 snoop_response_latency += snoop_result.second;
761 pkt->
cmd = snoop_response_cmd;
770 return snoop_response_latency;
775 PortID source_master_port_id,
783 Tick snoop_response_latency = 0;
790 for (
const auto&
p: dests) {
796 p->getId() == exclude_slave_port_id)
799 Tick latency =
p->sendAtomicSnoop(pkt);
809 assert(pkt->
cmd != orig_cmd);
814 snoop_response_cmd = pkt->
cmd;
815 snoop_response_latency = latency;
841 return std::make_pair(snoop_response_cmd, snoop_response_latency);
866 if (
p->checkFunctional(pkt)) {
889 if (
p->checkFunctional(pkt)) {
912 p->getId() != exclude_slave_port_id)
913 p->sendFunctionalSnoop(pkt);
960 .
desc(
"Total snoops (count)")
965 .
desc(
"Total snoop traffic (bytes)")
971 .desc(
"Request fanout histogram")
976 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...
PortID findPort(Addr addr)
Find which port connected to this crossbar (if any) should be given a packet with this address...
virtual void regStats()
Register statistics for this object.
Cycles is a wrapper class for representing cycle counts, i.e.
bool isBlockCached() const
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 std::string name() const
Return port name (for DPRINTF).
bool isExpressSnoop() const
bool bypassCaches() const
Should caches be bypassed?
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)
Timing function called by port when it is once again able to process requests.
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...
panic_if(!root,"Invalid expression\n")
Internal class to bridge between an incoming snoop response from a slave port and forwarding it throu...
const Cycles responseLatency
Cycles of response latency.
bool responderHadWritable() const
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...
int cmdToIndex() const
Return the index of this command.
Stats::Scalar snoopTraffic
const Cycles snoopResponseLatency
Cycles of snoop response latency.
Tick recvAtomic(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Atomic transaction.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
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...
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)
Function called by the port when the crossbar is recieving a Timing request packet.
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).
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...
Tick curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
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.
void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving a timing snoop request.
CoherentXBar(const CoherentXBarParams *p)
SnoopFilter * snoopFilter
A snoop filter that tracks cache line residency and can restrict the broadcast needed for probes...
const RequestPtr req
A pointer to the original request.
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
bool needsResponse() const
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
bool recvTimingResp(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving a Timing response packet.
void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
Forward a timing packet to our snoopers, potentially excluding one of the connected coherent masters ...
bool needsWritable() const
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool cacheResponding() const
bool isCleanEviction() const
Is this packet a clean eviction, including both actual clean evict packets, but also clean writebacks...
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
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.
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
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...
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...
Declaration of a coherent crossbar.
Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving an atomic snoop transaction.
static const int NumArgumentRegs M5_VAR_USED
std::vector< MasterPort * > masterPorts
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
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.
virtual const std::string name() const
MemCmd cmd
The command field of the packet.
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()
Register statistics for this object.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
const Cycles forwardLatency
Cycles of forward latency.
void setExpressSnoop()
The express snoop flag is used for two purposes.
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...
bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a timing snoop response.
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...
void recvFunctional(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Functional transaction.
bool sinkPacket(const PacketPtr pkt) const
Determine if the crossbar should sink the packet, as opposed to forwarding it, or responding...
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
std::vector< QueuedSlavePort * > snoopPorts