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)
87 if (if_name ==
"master" && idx <
masterPorts.size()) {
90 }
else if (if_name ==
"default") {
100 if (if_name ==
"slave" && idx <
slavePorts.size()) {
128 "Encountered header delay exceeding 1 us\n");
146 template <
typename SrcType,
typename DstType>
148 const std::string& _name) :
149 port(_port), xbar(_xbar), _name(_name), state(IDLE),
150 waitingForPeer(NULL), releaseEvent(this)
154 template <
typename SrcType,
typename DstType>
161 assert(state == BUSY);
165 xbar.schedule(releaseEvent, until);
168 occupancy += until -
curTick();
170 DPRINTF(
BaseXBar,
"The crossbar layer is now busy from tick %d to %d\n",
174 template <
typename SrcType,
typename DstType>
187 if (state == BUSY || waitingForPeer != NULL) {
189 assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
190 src_port) == waitingForLayer.end());
196 waitingForLayer.push_back(src_port);
205 template <
typename SrcType,
typename DstType>
211 assert(state == BUSY);
214 occupyLayer(busy_time);
217 template <
typename SrcType,
typename DstType>
224 assert(waitingForPeer == NULL);
229 waitingForPeer = src_port;
233 assert(state == BUSY);
236 occupyLayer(busy_time);
239 template <
typename SrcType,
typename DstType>
244 assert(state == BUSY);
245 assert(!releaseEvent.scheduled());
251 if (!waitingForLayer.empty()) {
254 if (waitingForPeer == NULL)
257 DPRINTF(Drain,
"Crossbar done draining, signaling drain manager\n");
263 template <
typename SrcType,
typename DstType>
268 assert(!waitingForLayer.empty());
271 assert(state == IDLE);
278 SrcType* retryingPort = waitingForLayer.front();
279 waitingForLayer.pop_front();
283 sendRetry(retryingPort);
288 if (state == RETRY) {
294 occupyLayer(xbar.clockEdge());
298 template <
typename SrcType,
typename DstType>
304 assert(waitingForPeer != NULL);
309 waitingForLayer.push_front(waitingForPeer);
312 waitingForPeer = NULL;
319 assert(state == BUSY);
346 DPRINTF(AddrRanges,
" found addr %#llx on default\n",
351 DPRINTF(AddrRanges,
"Unable to find destination for addr %#llx, "
352 "will use default port\n", addr);
358 fatal(
"Unable to find destination for addr %#llx on %s\n", addr,
366 DPRINTF(AddrRanges,
"Received range change from slave port %s\n",
383 DPRINTF(AddrRanges,
"Got address ranges from all slaves\n");
397 if (ranges.size() != 1)
398 fatal(
"Crossbar %s may only have a single default range",
408 if (
p->second == master_port_id)
419 for (
const auto&
r: ranges) {
420 DPRINTF(AddrRanges,
"Adding range %s for id %d\n",
421 r.to_string(), master_port_id);
424 fatal(
"%s has two ports responding within range %s:\n\t%s\n\t%s\n",
427 masterPorts[master_port_id]->getSlavePort().name(),
437 DPRINTF(AddrRanges,
"Aggregating address ranges\n");
443 fatal(
"Crossbar %s uses default range, but none provided",
447 DPRINTF(AddrRanges,
"-- Adding default %s\n",
456 if (
r.first.interleaved()) {
460 if (!intlv_ranges.empty() &&
461 !intlv_ranges.back().mergesWith(
r.first)) {
462 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
463 intlv_ranges.size());
469 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
470 merged_range.to_string());
472 intlv_ranges.clear();
474 intlv_ranges.push_back(
r.first);
480 DPRINTF(AddrRanges,
"-- Adding range %s\n",
481 r.first.to_string());
488 if (!intlv_ranges.empty()) {
489 DPRINTF(AddrRanges,
"-- Merging range from %d ranges\n",
490 intlv_ranges.size());
494 DPRINTF(AddrRanges,
"-- Adding merged range %s\n",
495 merged_range.to_string());
509 fatal(
"Range %s intersects the " \
510 "default range of %s but is not a " \
511 "subset\n",
r.to_string(),
name());
518 s->sendRangeChange();
537 DPRINTF(AddrRanges,
"Received address range request\n");
547 using namespace Stats;
552 .
desc(
"Transaction distribution")
558 const std::string &cstr = cmd.
toString();
565 .desc(
"Packet count per connected master and slave (bytes)")
571 .desc(
"Cumulative packet size per connected master and slave (bytes)")
590 template <
typename SrcType,
typename DstType>
598 DPRINTF(Drain,
"Crossbar not drained\n");
605 template <
typename SrcType,
typename DstType>
609 using namespace Stats;
612 .name(
name() +
".occupancy")
613 .desc(
"Layer occupancy (ticks)")
617 .name(
name() +
".utilization")
618 .desc(
"Layer utilization (%)")
622 utilization = 100 * occupancy /
simTicks;
const_iterator end() const
const_iterator insert(const AddrRange &r, const V &d)
void recvRetry()
Handle a retry from a neighbouring module.
PortID findPort(Addr addr)
Find which port connected to this crossbar (if any) should be given a packet with this address...
Derived & init(size_type _x, size_type _y)
virtual void regStats()
Register statistics for this object.
Derived & subname(off_type index, const std::string &name)
Set the subfield name for the given index, and marks this stat to print at the end of simulation...
void updatePortCache(short id, const AddrRange &range)
const PortID InvalidPortID
DrainState
Object drain/handover states.
const FlagsType nonan
Don't print if this is NAN.
PortID defaultPortID
Port that handles requests that don't match any of the interfaces.
panic_if(!root,"Invalid expression\n")
bool contains(const Addr &a) const
Determine if the range contains an address.
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
std::vector< bool > gotAddrRanges
Remember for each of the master ports of the crossbar if we got an address range from the connected s...
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
A BaseSlavePort is a protocol-agnostic slave port, responsible only for the structural connection to ...
Derived & init(size_type size)
Set this vector to have the given size.
AddrRangeMap< PortID > portMap
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
void succeededTiming(Tick busy_time)
Deal with a destination port accepting a packet by potentially removing the source port from the retr...
PortID checkPortCache(Addr addr) const
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
AddrRangeList xbarRanges
all contigous ranges seen by this crossbar
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.
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.
Stats::Vector transDist
Stats for transaction distribution and data passing through the crossbar.
BaseXBar(const BaseXBarParams *p)
std::string to_string() const
Get a string representation of the range.
const_iterator begin() const
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
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...
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...
const FlagsType total
Print the total.
const_iterator find(const AddrRange &r) const
BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
std::vector< MasterPort * > masterPorts
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
virtual const std::string name() const
void occupyLayer(Tick until)
Occupy the layer until until.
void releaseLayer()
Release the layer after being occupied and return to an idle state where we proceed to send a retry t...
Derived & ysubname(off_type index, const std::string &subname)
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
DrainState drain() override
Drain according to the normal semantics, so that the crossbar can tell the layer to drain...
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
void signalDrainDone() const
Signal that an object is drained.
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.
const std::string & toString() const
Return the string to a cmd given by idx.
void regStats()
Register stats for the layer.
DrainState drainState() const
Return the current drain state of an object.
bool tryTiming(SrcType *src_port)
Determine if the layer accepts a packet from a specific port.
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.
AddrRangeList getAddrRanges() const
Return the address ranges the crossbar is responsible for.
const FlagsType nozero
Don't print if this is zero.
void regStats() override
Register statistics for this object.
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
const bool useDefaultRange
If true, use address range provided by default device.
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.
BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
A function used to return the port associated with this object.