gem5  v20.1.0.0
noncoherent_xbar.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, 2018-2019 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 
46 #include "mem/noncoherent_xbar.hh"
47 
48 #include "base/logging.hh"
49 #include "base/trace.hh"
50 #include "debug/NoncoherentXBar.hh"
51 #include "debug/XBar.hh"
52 
53 NoncoherentXBar::NoncoherentXBar(const NoncoherentXBarParams *p)
54  : BaseXBar(p)
55 {
56  // create the ports based on the size of the memory-side port and
57  // CPU-side port vector ports, and the presence of the default port,
58  // the ports are enumerated starting from zero
59  for (int i = 0; i < p->port_mem_side_ports_connection_count; ++i) {
60  std::string portName = csprintf("%s.mem_side_port[%d]", name(), i);
61  RequestPort* bp = new NoncoherentXBarRequestPort(portName, *this, i);
62  memSidePorts.push_back(bp);
63  reqLayers.push_back(new ReqLayer(*bp, *this,
64  csprintf("reqLayer%d", i)));
65  }
66 
67  // see if we have a default CPU-side-port device connected and if so add
68  // our corresponding memory-side port
69  if (p->port_default_connection_count) {
70  defaultPortID = memSidePorts.size();
71  std::string portName = name() + ".default";
72  RequestPort* bp = new NoncoherentXBarRequestPort(portName, *this,
74  memSidePorts.push_back(bp);
75  reqLayers.push_back(new ReqLayer(*bp, *this, csprintf("reqLayer%d",
76  defaultPortID)));
77  }
78 
79  // create the CPU-side ports, once again starting at zero
80  for (int i = 0; i < p->port_cpu_side_ports_connection_count; ++i) {
81  std::string portName = csprintf("%s.cpu_side_ports[%d]", name(), i);
83  *this, i);
84  cpuSidePorts.push_back(bp);
85  respLayers.push_back(new RespLayer(*bp, *this,
86  csprintf("respLayer%d", i)));
87  }
88 }
89 
91 {
92  for (auto l: reqLayers)
93  delete l;
94  for (auto l: respLayers)
95  delete l;
96 }
97 
98 bool
100 {
101  // determine the source port based on the id
102  ResponsePort *src_port = cpuSidePorts[cpu_side_port_id];
103 
104  // we should never see express snoops on a non-coherent crossbar
105  assert(!pkt->isExpressSnoop());
106 
107  // determine the destination based on the address
108  PortID mem_side_port_id = findPort(pkt->getAddrRange());
109 
110  // test if the layer should be considered occupied for the current
111  // port
112  if (!reqLayers[mem_side_port_id]->tryTiming(src_port)) {
113  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x BUSY\n",
114  src_port->name(), pkt->cmdString(), pkt->getAddr());
115  return false;
116  }
117 
118  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x\n",
119  src_port->name(), pkt->cmdString(), pkt->getAddr());
120 
121  // store size and command as they might be modified when
122  // forwarding the packet
123  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
124  unsigned int pkt_cmd = pkt->cmdToIndex();
125 
126  // store the old header delay so we can restore it if needed
127  Tick old_header_delay = pkt->headerDelay;
128 
129  // a request sees the frontend and forward latency
130  Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod();
131 
132  // set the packet header and payload delay
133  calcPacketTiming(pkt, xbar_delay);
134 
135  // determine how long to be crossbar layer is busy
136  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
137 
138  // before forwarding the packet (and possibly altering it),
139  // remember if we are expecting a response
140  const bool expect_response = pkt->needsResponse() &&
141  !pkt->cacheResponding();
142 
143  // since it is a normal request, attempt to send the packet
144  bool success = memSidePorts[mem_side_port_id]->sendTimingReq(pkt);
145 
146  if (!success) {
147  DPRINTF(NoncoherentXBar, "recvTimingReq: src %s %s 0x%x RETRY\n",
148  src_port->name(), pkt->cmdString(), pkt->getAddr());
149 
150  // restore the header delay as it is additive
151  pkt->headerDelay = old_header_delay;
152 
153  // occupy until the header is sent
154  reqLayers[mem_side_port_id]->failedTiming(src_port,
155  clockEdge(Cycles(1)));
156 
157  return false;
158  }
159 
160  // remember where to route the response to
161  if (expect_response) {
162  assert(routeTo.find(pkt->req) == routeTo.end());
163  routeTo[pkt->req] = cpu_side_port_id;
164  }
165 
166  reqLayers[mem_side_port_id]->succeededTiming(packetFinishTime);
167 
168  // stats updates
169  pktCount[cpu_side_port_id][mem_side_port_id]++;
170  pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
171  transDist[pkt_cmd]++;
172 
173  return true;
174 }
175 
176 bool
178 {
179  // determine the source port based on the id
180  RequestPort *src_port = memSidePorts[mem_side_port_id];
181 
182  // determine the destination
183  const auto route_lookup = routeTo.find(pkt->req);
184  assert(route_lookup != routeTo.end());
185  const PortID cpu_side_port_id = route_lookup->second;
186  assert(cpu_side_port_id != InvalidPortID);
187  assert(cpu_side_port_id < respLayers.size());
188 
189  // test if the layer should be considered occupied for the current
190  // port
191  if (!respLayers[cpu_side_port_id]->tryTiming(src_port)) {
192  DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x BUSY\n",
193  src_port->name(), pkt->cmdString(), pkt->getAddr());
194  return false;
195  }
196 
197  DPRINTF(NoncoherentXBar, "recvTimingResp: src %s %s 0x%x\n",
198  src_port->name(), pkt->cmdString(), pkt->getAddr());
199 
200  // store size and command as they might be modified when
201  // forwarding the packet
202  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
203  unsigned int pkt_cmd = pkt->cmdToIndex();
204 
205  // a response sees the response latency
206  Tick xbar_delay = responseLatency * clockPeriod();
207 
208  // set the packet header and payload delay
209  calcPacketTiming(pkt, xbar_delay);
210 
211  // determine how long to be crossbar layer is busy
212  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
213 
214  // send the packet through the destination CPU-side port, and pay for
215  // any outstanding latency
216  Tick latency = pkt->headerDelay;
217  pkt->headerDelay = 0;
218  cpuSidePorts[cpu_side_port_id]->schedTimingResp(pkt,
219  curTick() + latency);
220 
221  // remove the request from the routing table
222  routeTo.erase(route_lookup);
223 
224  respLayers[cpu_side_port_id]->succeededTiming(packetFinishTime);
225 
226  // stats updates
227  pktCount[cpu_side_port_id][mem_side_port_id]++;
228  pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
229  transDist[pkt_cmd]++;
230 
231  return true;
232 }
233 
234 void
236 {
237  // responses never block on forwarding them, so the retry will
238  // always be coming from a port to which we tried to forward a
239  // request
240  reqLayers[mem_side_port_id]->recvRetry();
241 }
242 
243 Tick
245  MemBackdoorPtr *backdoor)
246 {
247  DPRINTF(NoncoherentXBar, "recvAtomic: packet src %s addr 0x%x cmd %s\n",
248  cpuSidePorts[cpu_side_port_id]->name(), pkt->getAddr(),
249  pkt->cmdString());
250 
251  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
252  unsigned int pkt_cmd = pkt->cmdToIndex();
253 
254  // determine the destination port
255  PortID mem_side_port_id = findPort(pkt->getAddrRange());
256 
257  // stats updates for the request
258  pktCount[cpu_side_port_id][mem_side_port_id]++;
259  pktSize[cpu_side_port_id][mem_side_port_id] += pkt_size;
260  transDist[pkt_cmd]++;
261 
262  // forward the request to the appropriate destination
263  auto mem_side_port = memSidePorts[mem_side_port_id];
264  Tick response_latency = backdoor ?
265  mem_side_port->sendAtomicBackdoor(pkt, *backdoor) :
266  mem_side_port->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[cpu_side_port_id][mem_side_port_id]++;
275  pktSize[cpu_side_port_id][mem_side_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  cpuSidePorts[cpu_side_port_id]->name(), pkt->getAddr(),
292  pkt->cmdString());
293  }
294 
295  // since our CPU-side ports are queued ports we need to check them as well
296  for (const auto& p : cpuSidePorts) {
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->trySatisfyFunctional(pkt)) {
301  if (pkt->needsResponse())
302  pkt->makeResponse();
303  return;
304  }
305  }
306 
307  // determine the destination port
308  PortID dest_id = findPort(pkt->getAddrRange());
309 
310  // forward the request to the appropriate destination
311  memSidePorts[dest_id]->sendFunctional(pkt);
312 }
313 
315 NoncoherentXBarParams::create()
316 {
317  return new NoncoherentXBar(this);
318 }
BaseXBar::forwardLatency
const Cycles forwardLatency
Definition: xbar.hh:309
ResponsePort
A ResponsePort is a specialization of a port.
Definition: port.hh:265
Packet::isResponse
bool isResponse() const
Definition: packet.hh:560
BaseXBar::cpuSidePorts
std::vector< QueuedResponsePort * > cpuSidePorts
The memory-side ports and CPU-side ports of the crossbar.
Definition: xbar.hh:376
Packet::getAddrRange
AddrRange getAddrRange() const
Get address range to which this packet belongs.
Definition: packet.cc:241
MemBackdoor
Definition: backdoor.hh:38
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:619
BaseXBar::transDist
Stats::Vector transDist
Stats for transaction distribution and data passing through the crossbar.
Definition: xbar.hh:399
NoncoherentXBar::recvFunctional
void recvFunctional(PacketPtr pkt, PortID cpu_side_port_id)
Definition: noncoherent_xbar.cc:285
BaseXBar::RespLayer
Definition: xbar.hh:257
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
Packet::isExpressSnoop
bool isExpressSnoop() const
Definition: packet.hh:662
Packet::payloadDelay
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:412
InvalidPortID
const PortID InvalidPortID
Definition: types.hh:238
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
noncoherent_xbar.hh
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
NoncoherentXBar::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt, PortID mem_side_port_id)
Definition: noncoherent_xbar.cc:177
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
BaseXBar::findPort
PortID findPort(AddrRange addr_range)
Find which port connected to this crossbar (if any) should be given a packet with this address range.
Definition: xbar.cc:327
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
NoncoherentXBar::recvReqRetry
void recvReqRetry(PortID mem_side_port_id)
Definition: noncoherent_xbar.cc:235
NoncoherentXBar::recvTimingReq
virtual bool recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id)
Definition: noncoherent_xbar.cc:99
BaseXBar::frontendLatency
const Cycles frontendLatency
Cycles of front-end pipeline including the delay to accept the request and to decode the address.
Definition: xbar.hh:308
Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:394
BaseXBar::defaultPortID
PortID defaultPortID
Port that handles requests that don't match any of the interfaces.
Definition: xbar.hh:380
NoncoherentXBar::NoncoherentXBarResponsePort
Declaration of the non-coherent crossbar CPU-side port type, one will be instantiated for each of the...
Definition: noncoherent_xbar.hh:82
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
Packet::cmdString
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:551
BaseXBar::ReqLayer
Definition: xbar.hh:234
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
Clocked::clockEdge
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...
Definition: clocked_object.hh:174
BaseXBar::routeTo
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:324
QueuedResponsePort
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
Definition: qport.hh:58
BaseXBar::pktSize
Stats::Vector2d pktSize
Definition: xbar.hh:401
Packet::cmdToIndex
int cmdToIndex() const
Return the index of this command.
Definition: packet.hh:554
RequestPort
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:74
NoncoherentXBar::NoncoherentXBarRequestPort
Declaration of the crossbar memory-side port type, one will be instantiated for each of the CPU-side ...
Definition: noncoherent_xbar.hh:138
Port::name
const std::string name() const
Return port name (for DPRINTF).
Definition: port.hh:106
Packet::makeResponse
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:1004
NoncoherentXBar::~NoncoherentXBar
virtual ~NoncoherentXBar()
Definition: noncoherent_xbar.cc:90
Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:214
Packet::hasData
bool hasData() const
Definition: packet.hh:576
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
BaseXBar::responseLatency
const Cycles responseLatency
Definition: xbar.hh:310
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
NoncoherentXBar::recvAtomicBackdoor
Tick recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id, MemBackdoorPtr *backdoor=nullptr)
Definition: noncoherent_xbar.cc:244
trace.hh
BaseXBar::pktCount
Stats::Vector2d pktCount
Definition: xbar.hh:400
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
Packet::isPrint
bool isPrint() const
Definition: packet.hh:584
NoncoherentXBar::reqLayers
std::vector< ReqLayer * > reqLayers
Declare the layers of this crossbar, one vector for requests and one for responses.
Definition: noncoherent_xbar.hh:74
BaseXBar
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
Definition: xbar.hh:68
NoncoherentXBar::NoncoherentXBar
NoncoherentXBar(const NoncoherentXBarParams *p)
Definition: noncoherent_xbar.cc:53
MipsISA::l
Bitfield< 5 > l
Definition: pra_constants.hh:320
NoncoherentXBar
A non-coherent crossbar connects a number of non-snooping memory-side ports and cpu_sides,...
Definition: noncoherent_xbar.hh:65
BaseXBar::calcPacketTiming
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
Definition: xbar.cc:101
csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
BaseXBar::memSidePorts
std::vector< RequestPort * > memSidePorts
Definition: xbar.hh:377
NoncoherentXBar::respLayers
std::vector< RespLayer * > respLayers
Definition: noncoherent_xbar.hh:75
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17