misc: Delete the now unnecessary create methods.
[gem5.git] / src / mem / port.hh
1 /*
2 * Copyright (c) 2011-2012,2015,2017 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) 2002-2005 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
41 /**
42 * @file
43 * Port Object Declaration.
44 */
45
46 #ifndef __MEM_PORT_HH__
47 #define __MEM_PORT_HH__
48
49 #include "base/addr_range.hh"
50 #include "mem/packet.hh"
51 #include "mem/protocol/atomic.hh"
52 #include "mem/protocol/functional.hh"
53 #include "mem/protocol/timing.hh"
54 #include "sim/port.hh"
55
56 class SimObject;
57
58 /** Forward declaration */
59 class MasterPort;
60 class SlavePort;
61
62 class ResponsePort;
63
64 /**
65 * A RequestPort is a specialisation of a Port, which
66 * implements the default protocol for the three different level of
67 * transport functions. In addition to the basic functionality of
68 * sending packets, it also has functions to receive range changes or
69 * determine if the port is snooping or not.
70 *
71 * The three protocols are atomic, timing, and functional, each with its own
72 * header file.
73 */
74 class RequestPort: public Port, public AtomicRequestProtocol,
75 public TimingRequestProtocol, public FunctionalRequestProtocol
76 {
77 friend class ResponsePort;
78
79 private:
80 ResponsePort *_responsePort;
81
82 protected:
83 SimObject &owner;
84
85 public:
86 RequestPort(const std::string& name, SimObject* _owner,
87 PortID id=InvalidPortID);
88 virtual ~RequestPort();
89
90 /**
91 * Bind this request port to a response port. This also does the
92 * mirror action and binds the response port to the request port.
93 */
94 void bind(Port &peer) override;
95
96 /**
97 * Unbind this request port and the associated response port.
98 */
99 void unbind() override;
100
101 /**
102 * Determine if this request port is snooping or not. The default
103 * implementation returns false and thus tells the neighbour we
104 * are not snooping. Any request port that wants to receive snoop
105 * requests (e.g. a cache connected to a bus) has to override this
106 * function.
107 *
108 * @return true if the port should be considered a snooper
109 */
110 virtual bool isSnooping() const { return false; }
111
112 /**
113 * Get the address ranges of the connected responder port.
114 */
115 AddrRangeList getAddrRanges() const;
116
117 /**
118 * Inject a PrintReq for the given address to print the state of
119 * that address throughout the memory system. For debugging.
120 */
121 void printAddr(Addr a);
122
123 public:
124 /* The atomic protocol. */
125
126 /**
127 * Send an atomic request packet, where the data is moved and the
128 * state is updated in zero time, without interleaving with other
129 * memory accesses.
130 *
131 * @param pkt Packet to send.
132 *
133 * @return Estimated latency of access.
134 */
135 Tick sendAtomic(PacketPtr pkt);
136
137 /**
138 * Send an atomic request packet like above, but also request a backdoor
139 * to the data being accessed.
140 *
141 * @param pkt Packet to send.
142 * @param backdoor Can be set to a back door pointer by the target to let
143 * caller have direct access to the requested data.
144 *
145 * @return Estimated latency of access.
146 */
147 Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor);
148
149 public:
150 /* The functional protocol. */
151
152 /**
153 * Send a functional request packet, where the data is instantly
154 * updated everywhere in the memory system, without affecting the
155 * current state of any block or moving the block.
156 *
157 * @param pkt Packet to send.
158 */
159 void sendFunctional(PacketPtr pkt) const;
160
161 public:
162 /* The timing protocol. */
163
164 /**
165 * Attempt to send a timing request to the responder port by calling
166 * its corresponding receive function. If the send does not
167 * succeed, as indicated by the return value, then the sender must
168 * wait for a recvReqRetry at which point it can re-issue a
169 * sendTimingReq.
170 *
171 * @param pkt Packet to send.
172 *
173 * @return If the send was succesful or not.
174 */
175 bool sendTimingReq(PacketPtr pkt);
176
177 /**
178 * Check if the responder can handle a timing request.
179 *
180 * If the send cannot be handled at the moment, as indicated by
181 * the return value, then the sender will receive a recvReqRetry
182 * at which point it can re-issue a sendTimingReq.
183 *
184 * @param pkt Packet to send.
185 *
186 * @return If the send was successful or not.
187 */
188 bool tryTiming(PacketPtr pkt) const;
189
190 /**
191 * Attempt to send a timing snoop response packet to the response
192 * port by calling its corresponding receive function. If the send
193 * does not succeed, as indicated by the return value, then the
194 * sender must wait for a recvRetrySnoop at which point it can
195 * re-issue a sendTimingSnoopResp.
196 *
197 * @param pkt Packet to send.
198 */
199 bool sendTimingSnoopResp(PacketPtr pkt);
200
201 /**
202 * Send a retry to the response port that previously attempted a
203 * sendTimingResp to this request port and failed. Note that this
204 * is virtual so that the "fake" snoop response port in the
205 * coherent crossbar can override the behaviour.
206 */
207 virtual void sendRetryResp();
208
209 protected:
210 /**
211 * Called to receive an address range change from the peer response
212 * port. The default implementation ignores the change and does
213 * nothing. Override this function in a derived class if the owner
214 * needs to be aware of the address ranges, e.g. in an
215 * interconnect component like a bus.
216 */
217 virtual void recvRangeChange() { }
218
219 /**
220 * Default implementations.
221 */
222 Tick
223 recvAtomicSnoop(PacketPtr pkt) override
224 {
225 panic("%s was not expecting an atomic snoop request\n", name());
226 return 0;
227 }
228
229 void
230 recvFunctionalSnoop(PacketPtr pkt) override
231 {
232 panic("%s was not expecting a functional snoop request\n", name());
233 }
234
235 void
236 recvTimingSnoopReq(PacketPtr pkt) override
237 {
238 panic("%s was not expecting a timing snoop request.\n", name());
239 }
240
241 void
242 recvRetrySnoopResp() override
243 {
244 panic("%s was not expecting a snoop retry.\n", name());
245 }
246 };
247
248 class [[deprecated]] MasterPort : public RequestPort
249 {
250 public:
251 MasterPort(const std::string& name, SimObject* _owner,
252 PortID id=InvalidPortID) : RequestPort(name, _owner, id)
253 {}
254 };
255
256 /**
257 * A ResponsePort is a specialization of a port. In addition to the
258 * basic functionality of sending packets to its requestor peer, it also
259 * has functions specific to a responder, e.g. to send range changes
260 * and get the address ranges that the port responds to.
261 *
262 * The three protocols are atomic, timing, and functional, each with its own
263 * header file.
264 */
265 class ResponsePort : public Port, public AtomicResponseProtocol,
266 public TimingResponseProtocol, public FunctionalResponseProtocol
267 {
268 friend class RequestPort;
269
270 private:
271 RequestPort* _requestPort;
272
273 bool defaultBackdoorWarned;
274
275 protected:
276 SimObject& owner;
277
278 public:
279 ResponsePort(const std::string& name, SimObject* _owner,
280 PortID id=InvalidPortID);
281 virtual ~ResponsePort();
282
283 /**
284 * Find out if the peer request port is snooping or not.
285 *
286 * @return true if the peer request port is snooping
287 */
288 bool isSnooping() const { return _requestPort->isSnooping(); }
289
290 /**
291 * Called by the owner to send a range change
292 */
293 void sendRangeChange() const { _requestPort->recvRangeChange(); }
294
295 /**
296 * Get a list of the non-overlapping address ranges the owner is
297 * responsible for. All response ports must override this function
298 * and return a populated list with at least one item.
299 *
300 * @return a list of ranges responded to
301 */
302 virtual AddrRangeList getAddrRanges() const = 0;
303
304 /**
305 * We let the request port do the work, so these don't do anything.
306 */
307 void unbind() override {}
308 void bind(Port &peer) override {}
309
310 public:
311 /* The atomic protocol. */
312
313 /**
314 * Send an atomic snoop request packet, where the data is moved
315 * and the state is updated in zero time, without interleaving
316 * with other memory accesses.
317 *
318 * @param pkt Snoop packet to send.
319 *
320 * @return Estimated latency of access.
321 */
322 Tick
323 sendAtomicSnoop(PacketPtr pkt)
324 {
325 try {
326 return AtomicResponseProtocol::sendSnoop(_requestPort, pkt);
327 } catch (UnboundPortException) {
328 reportUnbound();
329 }
330 }
331
332 public:
333 /* The functional protocol. */
334
335 /**
336 * Send a functional snoop request packet, where the data is
337 * instantly updated everywhere in the memory system, without
338 * affecting the current state of any block or moving the block.
339 *
340 * @param pkt Snoop packet to send.
341 */
342 void
343 sendFunctionalSnoop(PacketPtr pkt) const
344 {
345 try {
346 FunctionalResponseProtocol::sendSnoop(_requestPort, pkt);
347 } catch (UnboundPortException) {
348 reportUnbound();
349 }
350 }
351
352 public:
353 /* The timing protocol. */
354
355 /**
356 * Attempt to send a timing response to the request port by calling
357 * its corresponding receive function. If the send does not
358 * succeed, as indicated by the return value, then the sender must
359 * wait for a recvRespRetry at which point it can re-issue a
360 * sendTimingResp.
361 *
362 * @param pkt Packet to send.
363 *
364 * @return If the send was successful or not.
365 */
366 bool
367 sendTimingResp(PacketPtr pkt)
368 {
369 try {
370 return TimingResponseProtocol::sendResp(_requestPort, pkt);
371 } catch (UnboundPortException) {
372 reportUnbound();
373 }
374 }
375
376 /**
377 * Attempt to send a timing snoop request packet to the request port
378 * by calling its corresponding receive function. Snoop requests
379 * always succeed and hence no return value is needed.
380 *
381 * @param pkt Packet to send.
382 */
383 void
384 sendTimingSnoopReq(PacketPtr pkt)
385 {
386 try {
387 TimingResponseProtocol::sendSnoopReq(_requestPort, pkt);
388 } catch (UnboundPortException) {
389 reportUnbound();
390 }
391 }
392
393 /**
394 * Send a retry to the request port that previously attempted a
395 * sendTimingReq to this response port and failed.
396 */
397 void
398 sendRetryReq()
399 {
400 try {
401 TimingResponseProtocol::sendRetryReq(_requestPort);
402 } catch (UnboundPortException) {
403 reportUnbound();
404 }
405 }
406
407 /**
408 * Send a retry to the request port that previously attempted a
409 * sendTimingSnoopResp to this response port and failed.
410 */
411 void
412 sendRetrySnoopResp()
413 {
414 try {
415 TimingResponseProtocol::sendRetrySnoopResp(_requestPort);
416 } catch (UnboundPortException) {
417 reportUnbound();
418 }
419 }
420
421 protected:
422 /**
423 * Called by the request port to unbind. Should never be called
424 * directly.
425 */
426 void responderUnbind();
427
428 /**
429 * Called by the request port to bind. Should never be called
430 * directly.
431 */
432 void responderBind(RequestPort& request_port);
433
434 /**
435 * Default implementations.
436 */
437 Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override;
438
439 bool
440 tryTiming(PacketPtr pkt) override
441 {
442 panic("%s was not expecting a %s\n", name(), __func__);
443 }
444
445 bool
446 recvTimingSnoopResp(PacketPtr pkt) override
447 {
448 panic("%s was not expecting a timing snoop response\n", name());
449 }
450 };
451
452 class [[deprecated]] SlavePort : public ResponsePort
453 {
454 public:
455 SlavePort(const std::string& name, SimObject* _owner,
456 PortID id=InvalidPortID) : ResponsePort(name, _owner, id)
457 {}
458 };
459
460 inline Tick
461 RequestPort::sendAtomic(PacketPtr pkt)
462 {
463 try {
464 return AtomicRequestProtocol::send(_responsePort, pkt);
465 } catch (UnboundPortException) {
466 reportUnbound();
467 }
468 }
469
470 inline Tick
471 RequestPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
472 {
473 try {
474 return AtomicRequestProtocol::sendBackdoor(_responsePort,
475 pkt, backdoor);
476 } catch (UnboundPortException) {
477 reportUnbound();
478 }
479 }
480
481 inline void
482 RequestPort::sendFunctional(PacketPtr pkt) const
483 {
484 try {
485 return FunctionalRequestProtocol::send(_responsePort, pkt);
486 } catch (UnboundPortException) {
487 reportUnbound();
488 }
489 }
490
491 inline bool
492 RequestPort::sendTimingReq(PacketPtr pkt)
493 {
494 try {
495 return TimingRequestProtocol::sendReq(_responsePort, pkt);
496 } catch (UnboundPortException) {
497 reportUnbound();
498 }
499 }
500
501 inline bool
502 RequestPort::tryTiming(PacketPtr pkt) const
503 {
504 try {
505 return TimingRequestProtocol::trySend(_responsePort, pkt);
506 } catch (UnboundPortException) {
507 reportUnbound();
508 }
509 }
510
511 inline bool
512 RequestPort::sendTimingSnoopResp(PacketPtr pkt)
513 {
514 try {
515 return TimingRequestProtocol::sendSnoopResp(_responsePort, pkt);
516 } catch (UnboundPortException) {
517 reportUnbound();
518 }
519 }
520
521 inline void
522 RequestPort::sendRetryResp()
523 {
524 try {
525 TimingRequestProtocol::sendRetryResp(_responsePort);
526 } catch (UnboundPortException) {
527 reportUnbound();
528 }
529 }
530
531 #endif //__MEM_PORT_HH__