50 #include "debug/AddrRanges.hh"
51 #include "debug/Drain.hh"
52 #include "debug/XBar.hh"
59 frontendLatency(
p.frontend_latency),
60 forwardLatency(
p.forward_latency),
61 responseLatency(
p.response_latency),
62 headerLatency(
p.header_latency),
64 gotAddrRanges(
p.port_default_connection_count +
65 p.port_mem_side_ports_connection_count, false),
67 useDefaultRange(
p.use_default_range),
69 ADD_STAT(transDist, statistics::units::Count::get(),
70 "Transaction distribution"),
71 ADD_STAT(pktCount, statistics::units::Count::get(),
72 "Packet count per connected requestor and responder"),
73 ADD_STAT(pktSize, statistics::units::Byte::get(),
74 "Cumulative packet size per connected requestor and responder")
90 if (if_name ==
"mem_side_ports" && idx <
memSidePorts.size()) {
94 }
else if (if_name ==
"default") {
96 }
else if (if_name ==
"cpu_side_ports" && idx <
cpuSidePorts.size()) {
124 "Encountered header delay exceeding 1 us\n");
142 template <
typename SrcType,
typename DstType>
144 const std::string& _name) :
145 statistics::
Group(&_xbar, _name.c_str()),
146 port(_port), xbar(_xbar), _name(xbar.
name() +
"." + _name), state(IDLE),
147 waitingForPeer(NULL), releaseEvent([this]{ releaseLayer(); },
name()),
148 ADD_STAT(occupancy, statistics::units::Tick::get(),
"Layer occupancy (ticks)"),
149 ADD_STAT(utilization, statistics::units::Ratio::get(),
"Layer utilization")
161 template <
typename SrcType,
typename DstType>
168 assert(state ==
BUSY);
172 xbar.schedule(releaseEvent, until);
175 occupancy += until -
curTick();
177 DPRINTF(
BaseXBar,
"The crossbar layer is now busy from tick %d to %d\n",
181 template <
typename SrcType,
typename DstType>
194 if (state ==
BUSY || waitingForPeer != NULL) {
196 assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
197 src_port) == waitingForLayer.end());
203 waitingForLayer.push_back(src_port);
212 template <
typename SrcType,
typename DstType>
218 assert(state ==
BUSY);
221 occupyLayer(busy_time);
224 template <
typename SrcType,
typename DstType>
231 assert(waitingForPeer == NULL);
236 waitingForPeer = src_port;
240 assert(state ==
BUSY);
243 occupyLayer(busy_time);
246 template <
typename SrcType,
typename DstType>
251 assert(state ==
BUSY);
252 assert(!releaseEvent.scheduled());
258 if (!waitingForLayer.empty()) {
261 if (waitingForPeer == NULL)
263 }
else if (waitingForPeer == NULL && drainState() == DrainState::Draining) {
264 DPRINTF(Drain,
"Crossbar done draining, signaling drain manager\n");
270 template <
typename SrcType,
typename DstType>
275 assert(!waitingForLayer.empty());
278 assert(state == IDLE);
285 SrcType* retryingPort = waitingForLayer.front();
286 waitingForLayer.pop_front();
290 sendRetry(retryingPort);
295 if (state == RETRY) {
301 occupyLayer(xbar.clockEdge());
305 template <
typename SrcType,
typename DstType>
311 assert(waitingForPeer != NULL);
316 waitingForLayer.push_front(waitingForPeer);
319 waitingForPeer = NULL;
326 assert(state ==
BUSY);
335 assert(gotAllAddrRanges);
338 auto i = portMap.contains(addr_range);
339 if (
i != portMap.end()) {
344 if (useDefaultRange) {
345 if (addr_range.
isSubset(defaultRange)) {
346 DPRINTF(AddrRanges,
" found addr %s on default\n",
348 return defaultPortID;
351 DPRINTF(AddrRanges,
"Unable to find destination for %s, "
352 "will use default port\n", addr_range.
to_string());
353 return defaultPortID;
358 fatal(
"Unable to find destination for %s on %s\n", addr_range.
to_string(),
364 BaseXBar::recvRangeChange(
PortID mem_side_port_id)
366 DPRINTF(AddrRanges,
"Received range change from cpu_side_ports %s\n",
367 memSidePorts[mem_side_port_id]->getPeer());
371 gotAddrRanges[mem_side_port_id] =
true;
374 if (!gotAllAddrRanges) {
377 gotAllAddrRanges =
true;
379 while (gotAllAddrRanges &&
r != gotAddrRanges.end()) {
380 gotAllAddrRanges &= *
r++;
382 if (gotAllAddrRanges)
383 DPRINTF(AddrRanges,
"Got address ranges from all responders\n");
390 if (mem_side_port_id == defaultPortID) {
394 if (useDefaultRange) {
398 if (ranges.size() != 1)
399 fatal(
"Crossbar %s may only have a single default range",
402 defaultRange = ranges.front();
407 if (gotAddrRanges[mem_side_port_id]) {
408 for (
auto p = portMap.begin();
p != portMap.end(); ) {
409 if (
p->second == mem_side_port_id)
421 for (
const auto&
r: ranges) {
422 DPRINTF(AddrRanges,
"Adding range %s for id %d\n",
423 r.to_string(), mem_side_port_id);
424 if (portMap.insert(
r, mem_side_port_id) == portMap.end()) {
425 PortID conflict_id = portMap.intersects(
r)->second;
426 fatal(
"%s has two ports responding within range "
430 memSidePorts[mem_side_port_id]->getPeer(),
431 memSidePorts[conflict_id]->getPeer());
439 if (gotAllAddrRanges) {
440 DPRINTF(AddrRanges,
"Aggregating address ranges\n");
444 if (useDefaultRange) {
445 if (!gotAddrRanges[defaultPortID])
446 fatal(
"Crossbar %s uses default range, but none provided",
449 xbarRanges.push_back(defaultRange);
450 DPRINTF(AddrRanges,
"-- Adding default %s\n",
451 defaultRange.to_string());
457 for (
const auto&
r: portMap) {
459 if (
r.first.interleaved()) {
463 if (!intlv_ranges.empty() &&
464 !intlv_ranges.back().mergesWith(
r.first)) {
465 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
466 intlv_ranges.size());
469 if (!(useDefaultRange &&
470 merged_range.
isSubset(defaultRange))) {
471 xbarRanges.push_back(merged_range);
472 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
475 intlv_ranges.clear();
477 intlv_ranges.push_back(
r.first);
480 if (!(useDefaultRange &&
481 r.first.isSubset(defaultRange))) {
482 xbarRanges.push_back(
r.first);
483 DPRINTF(AddrRanges,
"-- Adding range %s\n",
484 r.first.to_string());
491 if (!intlv_ranges.empty()) {
492 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
493 intlv_ranges.size());
495 if (!(useDefaultRange && merged_range.
isSubset(defaultRange))) {
496 xbarRanges.push_back(merged_range);
497 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
506 if (useDefaultRange) {
507 for (
const auto&
r: xbarRanges) {
510 if (
r.intersects(defaultRange) &&
511 !
r.isSubset(defaultRange))
512 fatal(
"Range %s intersects the " \
513 "default range of %s but is not a " \
514 "subset\n",
r.to_string(),
name());
520 for (
const auto& port: cpuSidePorts)
521 port->sendRangeChange();
526 BaseXBar::getAddrRanges()
const
531 assert(gotAllAddrRanges);
538 DPRINTF(AddrRanges,
"Received address range request\n");
546 ClockedObject::regStats();
548 using namespace statistics;
551 .init(MemCmd::NUM_MEM_CMDS)
555 for (
int i = 0;
i < MemCmd::NUM_MEM_CMDS;
i++) {
557 const std::string &cstr = cmd.
toString();
558 transDist.subname(
i, cstr);
562 .init(cpuSidePorts.size(), memSidePorts.size())
566 .init(cpuSidePorts.size(), memSidePorts.size())
576 for (
int i = 0;
i < cpuSidePorts.size();
i++) {
577 pktCount.subname(
i, cpuSidePorts[
i]->getPeer().
name());
578 pktSize.subname(
i, cpuSidePorts[
i]->getPeer().
name());
579 for (
int j = 0;
j < memSidePorts.size();
j++) {
580 pktCount.ysubname(
j, memSidePorts[
j]->getPeer().
name());
581 pktSize.ysubname(
j, memSidePorts[
j]->getPeer().
name());
586 template <
typename SrcType,
typename DstType>
594 DPRINTF(Drain,
"Crossbar not drained\n");
595 return DrainState::Draining;
597 return DrainState::Drained;