54 #include "debug/AddrRanges.hh" 55 #include "debug/Drain.hh" 56 #include "debug/XBar.hh" 60 frontendLatency(p->frontend_latency),
61 forwardLatency(p->forward_latency),
62 responseLatency(p->response_latency),
64 gotAddrRanges(p->port_default_connection_count +
65 p->port_master_connection_count, false),
67 useDefaultRange(p->use_default_range),
69 transDist(this,
"trans_dist",
"Transaction distribution"),
70 pktCount(this,
"pkt_count",
71 "Packet count per connected master and slave (bytes)"),
72 pktSize(this,
"pkt_size",
73 "Cumulative packet size per connected master and slave (bytes)")
89 if (if_name ==
"master" && idx <
masterPorts.size()) {
92 }
else if (if_name ==
"default") {
94 }
else if (if_name ==
"slave" && idx <
slavePorts.size()) {
122 "Encountered header delay exceeding 1 us\n");
140 template <
typename SrcType,
typename DstType>
142 const std::string& _name) :
144 port(_port), xbar(_xbar), _name(xbar.
name() +
"." + _name), state(IDLE),
145 waitingForPeer(NULL), releaseEvent([this]{ releaseLayer(); },
name()),
146 ADD_STAT(occupancy,
"Layer occupancy (ticks)"),
147 ADD_STAT(utilization,
"Layer utilization (%)")
156 utilization = 100 * occupancy /
simTicks;
159 template <
typename SrcType,
typename DstType>
166 assert(state == BUSY);
170 xbar.schedule(releaseEvent, until);
173 occupancy += until -
curTick();
175 DPRINTF(
BaseXBar,
"The crossbar layer is now busy from tick %d to %d\n",
179 template <
typename SrcType,
typename DstType>
192 if (state == BUSY || waitingForPeer != NULL) {
194 assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
195 src_port) == waitingForLayer.end());
201 waitingForLayer.push_back(src_port);
210 template <
typename SrcType,
typename DstType>
216 assert(state == BUSY);
219 occupyLayer(busy_time);
222 template <
typename SrcType,
typename DstType>
229 assert(waitingForPeer == NULL);
234 waitingForPeer = src_port;
238 assert(state == BUSY);
241 occupyLayer(busy_time);
244 template <
typename SrcType,
typename DstType>
249 assert(state == BUSY);
250 assert(!releaseEvent.scheduled());
256 if (!waitingForLayer.empty()) {
259 if (waitingForPeer == NULL)
262 DPRINTF(Drain,
"Crossbar done draining, signaling drain manager\n");
268 template <
typename SrcType,
typename DstType>
273 assert(!waitingForLayer.empty());
276 assert(state == IDLE);
283 SrcType* retryingPort = waitingForLayer.front();
284 waitingForLayer.pop_front();
288 sendRetry(retryingPort);
293 if (state == RETRY) {
299 occupyLayer(xbar.clockEdge());
303 template <
typename SrcType,
typename DstType>
309 assert(waitingForPeer != NULL);
314 waitingForLayer.push_front(waitingForPeer);
317 waitingForPeer = NULL;
324 assert(state == BUSY);
333 assert(gotAllAddrRanges);
336 auto i = portMap.contains(addr_range);
337 if (
i != portMap.end()) {
342 if (useDefaultRange) {
343 if (addr_range.
isSubset(defaultRange)) {
344 DPRINTF(AddrRanges,
" found addr %s on default\n",
346 return defaultPortID;
349 DPRINTF(AddrRanges,
"Unable to find destination for %s, " 350 "will use default port\n", addr_range.
to_string());
351 return defaultPortID;
356 fatal(
"Unable to find destination for %s on %s\n", addr_range.
to_string(),
364 DPRINTF(AddrRanges,
"Received range change from slave port %s\n",
365 masterPorts[master_port_id]->getPeer());
369 gotAddrRanges[master_port_id] =
true;
372 if (!gotAllAddrRanges) {
375 gotAllAddrRanges =
true;
377 while (gotAllAddrRanges && r != gotAddrRanges.end()) {
378 gotAllAddrRanges &= *r++;
380 if (gotAllAddrRanges)
381 DPRINTF(AddrRanges,
"Got address ranges from all slaves\n");
388 if (master_port_id == defaultPortID) {
392 if (useDefaultRange) {
393 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
395 if (ranges.size() != 1)
396 fatal(
"Crossbar %s may only have a single default range",
399 defaultRange = ranges.front();
404 if (gotAddrRanges[master_port_id]) {
405 for (
auto p = portMap.begin();
p != portMap.end(); ) {
406 if (
p->second == master_port_id)
415 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
417 for (
const auto&
r: ranges) {
418 DPRINTF(AddrRanges,
"Adding range %s for id %d\n",
419 r.to_string(), master_port_id);
420 if (portMap.insert(
r, master_port_id) == portMap.end()) {
421 PortID conflict_id = portMap.intersects(
r)->second;
422 fatal(
"%s has two ports responding within range " 426 masterPorts[master_port_id]->getPeer(),
427 masterPorts[conflict_id]->getPeer());
435 if (gotAllAddrRanges) {
436 DPRINTF(AddrRanges,
"Aggregating address ranges\n");
440 if (useDefaultRange) {
441 if (!gotAddrRanges[defaultPortID])
442 fatal(
"Crossbar %s uses default range, but none provided",
445 xbarRanges.push_back(defaultRange);
446 DPRINTF(AddrRanges,
"-- Adding default %s\n",
447 defaultRange.to_string());
453 for (
const auto&
r: portMap) {
455 if (
r.first.interleaved()) {
459 if (!intlv_ranges.empty() &&
460 !intlv_ranges.back().mergesWith(
r.first)) {
461 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
462 intlv_ranges.size());
465 if (!(useDefaultRange &&
466 merged_range.isSubset(defaultRange))) {
467 xbarRanges.push_back(merged_range);
468 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
469 merged_range.to_string());
471 intlv_ranges.clear();
473 intlv_ranges.push_back(
r.first);
476 if (!(useDefaultRange &&
477 r.first.isSubset(defaultRange))) {
478 xbarRanges.push_back(
r.first);
479 DPRINTF(AddrRanges,
"-- Adding range %s\n",
480 r.first.to_string());
487 if (!intlv_ranges.empty()) {
488 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
489 intlv_ranges.size());
491 if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
492 xbarRanges.push_back(merged_range);
493 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
494 merged_range.to_string());
502 if (useDefaultRange) {
503 for (
const auto&
r: xbarRanges) {
506 if (
r.intersects(defaultRange) &&
507 !
r.isSubset(defaultRange))
508 fatal(
"Range %s intersects the " \
509 "default range of %s but is not a " \
510 "subset\n",
r.to_string(),
name());
516 for (
const auto&
s: slavePorts)
517 s->sendRangeChange();
527 assert(gotAllAddrRanges);
534 DPRINTF(AddrRanges,
"Received address range request\n");
544 using namespace Stats;
553 const std::string &cstr = cmd.
toString();
554 transDist.subname(
i, cstr);
558 .init(slavePorts.size(), masterPorts.size())
562 .init(slavePorts.size(), masterPorts.size())
571 for (
int i = 0;
i < slavePorts.size();
i++) {
572 pktCount.subname(
i, slavePorts[
i]->getPeer().
name());
573 pktSize.subname(
i, slavePorts[
i]->getPeer().
name());
574 for (
int j = 0;
j < masterPorts.size();
j++) {
575 pktCount.ysubname(
j, masterPorts[
j]->getPeer().
name());
576 pktSize.ysubname(
j, masterPorts[
j]->getPeer().
name());
581 template <
typename SrcType,
typename DstType>
589 DPRINTF(Drain,
"Crossbar not drained\n");
Ports are used to interface objects to each other.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
void recvRetry()
Handle a retry from a neighbouring module.
#define fatal(...)
This implements a cprintf based fatal() function.
const std::string & name()
const PortID InvalidPortID
DrainState
Object drain/handover states.
const FlagsType nonan
Don't print if this is NAN.
const std::string & toString() const
Return the string to a cmd given by idx.
PortID defaultPortID
Port that handles requests that don't match any of the interfaces.
bool isSubset(const AddrRange &r) const
Determine if this range is a subset of another range, i.e.
virtual void regStats()
Callback to set stat parameters.
AddrRangeList getAddrRanges() const
Return the address ranges the crossbar is responsible for.
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
void regStats() override
Callback to set stat parameters.
void succeededTiming(Tick busy_time)
Deal with a destination port accepting a packet by potentially removing the source port from the retr...
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Tick curTick()
The current simulated tick.
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
const uint32_t width
the width of the xbar in bytes
uint64_t Tick
Tick count type.
BaseXBar(const BaseXBarParams *p)
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
A function used to return the port associated with this object.
Draining buffers pending serialization/handover.
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
void failedTiming(SrcType *src_port, Tick busy_time)
Deal with a destination port not accepting a packet by potentially adding the source port to the retr...
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
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...
const FlagsType total
Print the total.
std::vector< MasterPort * > masterPorts
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
void occupyLayer(Tick until)
void releaseLayer()
Release the layer after being occupied and return to an idle state where we proceed to send a retry t...
DrainState drain() override
Drain according to the normal semantics, so that the crossbar can tell the layer to drain...
PortID findPort(AddrRange addr_range)
Find which port connected to this crossbar (if any) should be given a packet with this address range...
T divCeil(const T &a, const U &b)
Layer(DstType &_port, BaseXBar &_xbar, const std::string &_name)
Create a layer and give it a name.
bool tryTiming(SrcType *src_port)
Determine if the layer accepts a packet from a specific port.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
std::string to_string() const
Get a string representation of the range.
const FlagsType nozero
Don't print if this is zero.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
void retryWaiting()
Send a retry to the port at the head of waitingForLayer.
Declaration of an abstract crossbar base class.
virtual void recvRangeChange(PortID master_port_id)
Function called by the port when the crossbar is recieving a range change.