gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
noncoherent_xbar.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2006 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Authors: Ali Saidi
41  * Andreas Hansson
42  * William Wang
43  */
44 
50 #include "mem/noncoherent_xbar.hh"
51 
52 #include "base/misc.hh"
53 #include "base/trace.hh"
54 #include "debug/NoncoherentXBar.hh"
55 #include "debug/XBar.hh"
56 
57 NoncoherentXBar::NoncoherentXBar(const NoncoherentXBarParams *p)
58  : BaseXBar(p)
59 {
60  // create the ports based on the size of the master and slave
61  // vector ports, and the presence of the default port, the ports
62  // are enumerated starting from zero
63  for (int i = 0; i < p->port_master_connection_count; ++i) {
64  std::string portName = csprintf("%s.master[%d]", name(), i);
65  MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this, i);
66  masterPorts.push_back(bp);
67  reqLayers.push_back(new ReqLayer(*bp, *this,
68  csprintf(".reqLayer%d", i)));
69  }
70 
71  // see if we have a default slave device connected and if so add
72  // our corresponding master port
73  if (p->port_default_connection_count) {
74  defaultPortID = masterPorts.size();
75  std::string portName = name() + ".default";
76  MasterPort* bp = new NoncoherentXBarMasterPort(portName, *this,
78  masterPorts.push_back(bp);
79  reqLayers.push_back(new ReqLayer(*bp, *this, csprintf(".reqLayer%d",
80  defaultPortID)));
81  }
82 
83  // create the slave ports, once again starting at zero
84  for (int i = 0; i < p->port_slave_connection_count; ++i) {
85  std::string portName = csprintf("%s.slave[%d]", name(), i);
86  QueuedSlavePort* bp = new NoncoherentXBarSlavePort(portName, *this, i);
87  slavePorts.push_back(bp);
88  respLayers.push_back(new RespLayer(*bp, *this,
89  csprintf(".respLayer%d", i)));
90  }
91 
93 }
94 
96 {
97  for (auto l: reqLayers)
98  delete l;
99  for (auto l: respLayers)
100  delete l;
101 }
102 
103 bool
105 {
106  // determine the source port based on the id
107  SlavePort *src_port = slavePorts[slave_port_id];
108 
109  // we should never see express snoops on a non-coherent crossbar
110  assert(!pkt->isExpressSnoop());
111 
112  // determine the destination based on the address
113  PortID master_port_id = findPort(pkt->getAddr());
114 
115  // test if the layer should be considered occupied for the current
116  // port
117  if (!reqLayers[master_port_id]->tryTiming(src_port)) {
118  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n",
119  src_port->name(), pkt->cmdString(), pkt->getAddr());
120  return false;
121  }
122 
123  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x\n",
124  src_port->name(), pkt->cmdString(), pkt->getAddr());
125 
126  // store size and command as they might be modified when
127  // forwarding the packet
128  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
129  unsigned int pkt_cmd = pkt->cmdToIndex();
130 
131  // store the old header delay so we can restore it if needed
132  Tick old_header_delay = pkt->headerDelay;
133 
134  // a request sees the frontend and forward latency
135  Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod();
136 
137  // set the packet header and payload delay
138  calcPacketTiming(pkt, xbar_delay);
139 
140  // determine how long to be crossbar layer is busy
141  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
142 
143  // before forwarding the packet (and possibly altering it),
144  // remember if we are expecting a response
145  const bool expect_response = pkt->needsResponse() &&
146  !pkt->cacheResponding();
147 
148  // since it is a normal request, attempt to send the packet
149  bool success = masterPorts[master_port_id]->sendTimingReq(pkt);
150 
151  if (!success) {
152  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
153  src_port->name(), pkt->cmdString(), pkt->getAddr());
154 
155  // restore the header delay as it is additive
156  pkt->headerDelay = old_header_delay;
157 
158  // occupy until the header is sent
159  reqLayers[master_port_id]->failedTiming(src_port,
160  clockEdge(Cycles(1)));
161 
162  return false;
163  }
164 
165  // remember where to route the response to
166  if (expect_response) {
167  assert(routeTo.find(pkt->req) == routeTo.end());
168  routeTo[pkt->req] = slave_port_id;
169  }
170 
171  reqLayers[master_port_id]->succeededTiming(packetFinishTime);
172 
173  // stats updates
174  pktCount[slave_port_id][master_port_id]++;
175  pktSize[slave_port_id][master_port_id] += pkt_size;
176  transDist[pkt_cmd]++;
177 
178  return true;
179 }
180 
181 bool
183 {
184  // determine the source port based on the id
185  MasterPort *src_port = masterPorts[master_port_id];
186 
187  // determine the destination
188  const auto route_lookup = routeTo.find(pkt->req);
189  assert(route_lookup != routeTo.end());
190  const PortID slave_port_id = route_lookup->second;
191  assert(slave_port_id != InvalidPortID);
192  assert(slave_port_id < respLayers.size());
193 
194  // test if the layer should be considered occupied for the current
195  // port
196  if (!respLayers[slave_port_id]->tryTiming(src_port)) {
197  DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n",
198  src_port->name(), pkt->cmdString(), pkt->getAddr());
199  return false;
200  }
201 
202  DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x\n",
203  src_port->name(), pkt->cmdString(), pkt->getAddr());
204 
205  // store size and command as they might be modified when
206  // forwarding the packet
207  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
208  unsigned int pkt_cmd = pkt->cmdToIndex();
209 
210  // a response sees the response latency
211  Tick xbar_delay = responseLatency * clockPeriod();
212 
213  // set the packet header and payload delay
214  calcPacketTiming(pkt, xbar_delay);
215 
216  // determine how long to be crossbar layer is busy
217  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
218 
219  // send the packet through the destination slave port, and pay for
220  // any outstanding latency
221  Tick latency = pkt->headerDelay;
222  pkt->headerDelay = 0;
223  slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency);
224 
225  // remove the request from the routing table
226  routeTo.erase(route_lookup);
227 
228  respLayers[slave_port_id]->succeededTiming(packetFinishTime);
229 
230  // stats updates
231  pktCount[slave_port_id][master_port_id]++;
232  pktSize[slave_port_id][master_port_id] += pkt_size;
233  transDist[pkt_cmd]++;
234 
235  return true;
236 }
237 
238 void
240 {
241  // responses never block on forwarding them, so the retry will
242  // always be coming from a port to which we tried to forward a
243  // request
244  reqLayers[master_port_id]->recvRetry();
245 }
246 
247 Tick
249 {
250  DPRINTF(NoncoherentXBar, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
251  slavePorts[slave_port_id]->name(), pkt->getAddr(),
252  pkt->cmdString());
253 
254  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
255  unsigned int pkt_cmd = pkt->cmdToIndex();
256 
257  // determine the destination port
258  PortID master_port_id = findPort(pkt->getAddr());
259 
260  // stats updates for the request
261  pktCount[slave_port_id][master_port_id]++;
262  pktSize[slave_port_id][master_port_id] += pkt_size;
263  transDist[pkt_cmd]++;
264 
265  // forward the request to the appropriate destination
266  Tick response_latency = masterPorts[master_port_id]->sendAtomic(pkt);
267 
268  // add the response data
269  if (pkt->isResponse()) {
270  pkt_size = pkt->hasData() ? pkt->getSize() : 0;
271  pkt_cmd = pkt->cmdToIndex();
272 
273  // stats updates
274  pktCount[slave_port_id][master_port_id]++;
275  pktSize[slave_port_id][master_port_id] += pkt_size;
276  transDist[pkt_cmd]++;
277  }
278 
279  // @todo: Not setting first-word time
280  pkt->payloadDelay = response_latency;
281  return response_latency;
282 }
283 
284 void
286 {
287  if (!pkt->isPrint()) {
288  // don't do DPRINTFs on PrintReq as it clutters up the output
290  "recvFunctional: packet src %s addr 0x%x cmd %s\n",
291  slavePorts[slave_port_id]->name(), pkt->getAddr(),
292  pkt->cmdString());
293  }
294 
295  // since our slave ports are queued ports we need to check them as well
296  for (const auto& p : slavePorts) {
297  // if we find a response that has the data, then the
298  // downstream caches/memories may be out of date, so simply stop
299  // here
300  if (p->checkFunctional(pkt)) {
301  if (pkt->needsResponse())
302  pkt->makeResponse();
303  return;
304  }
305  }
306 
307  // determine the destination port
308  PortID dest_id = findPort(pkt->getAddr());
309 
310  // forward the request to the appropriate destination
311  masterPorts[dest_id]->sendFunctional(pkt);
312 }
313 
315 NoncoherentXBarParams::create()
316 {
317  return new NoncoherentXBar(this);
318 }
319 
320 void
322 {
323  // register the stats of the base class and our layers
325  for (auto l: reqLayers)
326  l->regStats();
327  for (auto l: respLayers)
328  l->regStats();
329 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:212
PortID findPort(Addr addr)
Find which port connected to this crossbar (if any) should be given a packet with this address...
Definition: xbar.cc:324
virtual void regStats()
Register statistics for this object.
Definition: xbar.cc:543
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
Declaration of the non-coherent crossbar slave port type, one will be instantiated for each of the ma...
bool isPrint() const
Definition: packet.hh:529
virtual bool recvTimingResp(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving a Timing response packet.
Bitfield< 7 > i
Definition: miscregs.hh:1378
const PortID InvalidPortID
Definition: types.hh:182
std::vector< ReqLayer * > reqLayers
Declare the layers of this crossbar, one vector for requests and one for responses.
const std::string name() const
Return port name (for DPRINTF).
Definition: port.hh:99
bool isExpressSnoop() const
Definition: packet.hh:601
std::vector< RespLayer * > respLayers
bool hasData() const
Definition: packet.hh:521
PortID defaultPortID
Port that handles requests that don't match any of the interfaces.
Definition: xbar.hh:432
std::unordered_map< RequestPtr, PortID > routeTo
Remember where request packets came from so that we can route responses to the appropriate port...
Definition: xbar.hh:330
const Cycles responseLatency
Cycles of response latency.
Definition: xbar.hh:318
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
Definition: qport.hh:59
A SlavePort is a specialisation of a port.
Definition: port.hh:331
virtual void regStats()
stats
int cmdToIndex() const
Return the index of this command.
Definition: packet.hh:500
NoncoherentXBar(const NoncoherentXBarParams *p)
virtual 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.
Definition: xbar.hh:73
void recvFunctional(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Functional transaction.
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.
Definition: core.hh:47
void recvReqRetry(PortID master_port_id)
Timing function called by port when it is once again able to process requests.
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:340
Tick recvAtomic(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Atomic transaction.
uint64_t Tick
Tick count type.
Definition: types.hh:63
Stats::Vector transDist
Stats for transaction distribution and data passing through the crossbar.
Definition: xbar.hh:451
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
Definition: xbar.cc:109
bool needsResponse() const
Definition: packet.hh:516
bool cacheResponding() const
Definition: packet.hh:558
virtual ~NoncoherentXBar()
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:358
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
const Cycles frontendLatency
Cycles of front-end pipeline including the delay to accept the request and to decode the address...
Definition: xbar.hh:314
A non-coherent crossbar connects a number of non-snooping masters and slaves, and routes the request ...
std::vector< MasterPort * > masterPorts
Definition: xbar.hh:429
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:845
Tick clockPeriod() const
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
Definition: xbar.hh:428
virtual const std::string name() const
Definition: sim_object.hh:117
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:497
Declaration of the crossbar master port type, one will be instantiated for each of the slave ports co...
Declaration of a non-coherent crossbar.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
const Cycles forwardLatency
Cycles of forward latency.
Definition: xbar.hh:316
void clearPortCache()
Definition: xbar.hh:394
unsigned getSize() const
Definition: packet.hh:649
Bitfield< 0 > p
Stats::Vector2d pktSize
Definition: xbar.hh:453
Bitfield< 5 > l
bool isResponse() const
Definition: packet.hh:506
Addr getAddr() const
Definition: packet.hh:639
Stats::Vector2d pktCount
Definition: xbar.hh:452

Generated on Fri Jun 9 2017 13:03:49 for gem5 by doxygen 1.8.6