2 * Copyright (c) 2011-2012,2015,2017 ARM Limited
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.
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * All rights reserved.
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.
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.
43 * Port Object Declaration.
46 #ifndef __MEM_PORT_HH__
47 #define __MEM_PORT_HH__
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"
58 /** Forward declaration */
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.
71 * The three protocols are atomic, timing, and functional, each with its own
74 class RequestPort: public Port, public AtomicRequestProtocol,
75 public TimingRequestProtocol, public FunctionalRequestProtocol
77 friend class ResponsePort;
80 ResponsePort *_responsePort;
86 RequestPort(const std::string& name, SimObject* _owner,
87 PortID id=InvalidPortID);
88 virtual ~RequestPort();
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.
94 void bind(Port &peer) override;
97 * Unbind this request port and the associated response port.
99 void unbind() override;
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
108 * @return true if the port should be considered a snooper
110 virtual bool isSnooping() const { return false; }
113 * Get the address ranges of the connected responder port.
115 AddrRangeList getAddrRanges() const;
118 * Inject a PrintReq for the given address to print the state of
119 * that address throughout the memory system. For debugging.
121 void printAddr(Addr a);
124 /* The atomic protocol. */
127 * Send an atomic request packet, where the data is moved and the
128 * state is updated in zero time, without interleaving with other
131 * @param pkt Packet to send.
133 * @return Estimated latency of access.
135 Tick sendAtomic(PacketPtr pkt);
138 * Send an atomic request packet like above, but also request a backdoor
139 * to the data being accessed.
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.
145 * @return Estimated latency of access.
147 Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor);
150 /* The functional protocol. */
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.
157 * @param pkt Packet to send.
159 void sendFunctional(PacketPtr pkt) const;
162 /* The timing protocol. */
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
171 * @param pkt Packet to send.
173 * @return If the send was succesful or not.
175 bool sendTimingReq(PacketPtr pkt);
178 * Check if the responder can handle a timing request.
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.
184 * @param pkt Packet to send.
186 * @return If the send was successful or not.
188 bool tryTiming(PacketPtr pkt) const;
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.
197 * @param pkt Packet to send.
199 bool sendTimingSnoopResp(PacketPtr pkt);
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.
207 virtual void sendRetryResp();
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.
217 virtual void recvRangeChange() { }
220 * Default implementations.
223 recvAtomicSnoop(PacketPtr pkt) override
225 panic("%s was not expecting an atomic snoop request\n", name());
230 recvFunctionalSnoop(PacketPtr pkt) override
232 panic("%s was not expecting a functional snoop request\n", name());
236 recvTimingSnoopReq(PacketPtr pkt) override
238 panic("%s was not expecting a timing snoop request.\n", name());
242 recvRetrySnoopResp() override
244 panic("%s was not expecting a snoop retry.\n", name());
248 class [[deprecated]] MasterPort : public RequestPort
251 MasterPort(const std::string& name, SimObject* _owner,
252 PortID id=InvalidPortID) : RequestPort(name, _owner, id)
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.
262 * The three protocols are atomic, timing, and functional, each with its own
265 class ResponsePort : public Port, public AtomicResponseProtocol,
266 public TimingResponseProtocol, public FunctionalResponseProtocol
268 friend class RequestPort;
271 RequestPort* _requestPort;
273 bool defaultBackdoorWarned;
279 ResponsePort(const std::string& name, SimObject* _owner,
280 PortID id=InvalidPortID);
281 virtual ~ResponsePort();
284 * Find out if the peer request port is snooping or not.
286 * @return true if the peer request port is snooping
288 bool isSnooping() const { return _requestPort->isSnooping(); }
291 * Called by the owner to send a range change
293 void sendRangeChange() const { _requestPort->recvRangeChange(); }
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.
300 * @return a list of ranges responded to
302 virtual AddrRangeList getAddrRanges() const = 0;
305 * We let the request port do the work, so these don't do anything.
307 void unbind() override {}
308 void bind(Port &peer) override {}
311 /* The atomic protocol. */
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.
318 * @param pkt Snoop packet to send.
320 * @return Estimated latency of access.
323 sendAtomicSnoop(PacketPtr pkt)
326 return AtomicResponseProtocol::sendSnoop(_requestPort, pkt);
327 } catch (UnboundPortException) {
333 /* The functional protocol. */
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.
340 * @param pkt Snoop packet to send.
343 sendFunctionalSnoop(PacketPtr pkt) const
346 FunctionalResponseProtocol::sendSnoop(_requestPort, pkt);
347 } catch (UnboundPortException) {
353 /* The timing protocol. */
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
362 * @param pkt Packet to send.
364 * @return If the send was successful or not.
367 sendTimingResp(PacketPtr pkt)
370 return TimingResponseProtocol::sendResp(_requestPort, pkt);
371 } catch (UnboundPortException) {
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.
381 * @param pkt Packet to send.
384 sendTimingSnoopReq(PacketPtr pkt)
387 TimingResponseProtocol::sendSnoopReq(_requestPort, pkt);
388 } catch (UnboundPortException) {
394 * Send a retry to the request port that previously attempted a
395 * sendTimingReq to this response port and failed.
401 TimingResponseProtocol::sendRetryReq(_requestPort);
402 } catch (UnboundPortException) {
408 * Send a retry to the request port that previously attempted a
409 * sendTimingSnoopResp to this response port and failed.
415 TimingResponseProtocol::sendRetrySnoopResp(_requestPort);
416 } catch (UnboundPortException) {
423 * Called by the request port to unbind. Should never be called
426 void responderUnbind();
429 * Called by the request port to bind. Should never be called
432 void responderBind(RequestPort& request_port);
435 * Default implementations.
437 Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override;
440 tryTiming(PacketPtr pkt) override
442 panic("%s was not expecting a %s\n", name(), __func__);
446 recvTimingSnoopResp(PacketPtr pkt) override
448 panic("%s was not expecting a timing snoop response\n", name());
452 class [[deprecated]] SlavePort : public ResponsePort
455 SlavePort(const std::string& name, SimObject* _owner,
456 PortID id=InvalidPortID) : ResponsePort(name, _owner, id)
461 RequestPort::sendAtomic(PacketPtr pkt)
464 return AtomicRequestProtocol::send(_responsePort, pkt);
465 } catch (UnboundPortException) {
471 RequestPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
474 return AtomicRequestProtocol::sendBackdoor(_responsePort,
476 } catch (UnboundPortException) {
482 RequestPort::sendFunctional(PacketPtr pkt) const
485 return FunctionalRequestProtocol::send(_responsePort, pkt);
486 } catch (UnboundPortException) {
492 RequestPort::sendTimingReq(PacketPtr pkt)
495 return TimingRequestProtocol::sendReq(_responsePort, pkt);
496 } catch (UnboundPortException) {
502 RequestPort::tryTiming(PacketPtr pkt) const
505 return TimingRequestProtocol::trySend(_responsePort, pkt);
506 } catch (UnboundPortException) {
512 RequestPort::sendTimingSnoopResp(PacketPtr pkt)
515 return TimingRequestProtocol::sendSnoopResp(_responsePort, pkt);
516 } catch (UnboundPortException) {
522 RequestPort::sendRetryResp()
525 TimingRequestProtocol::sendRetryResp(_responsePort);
526 } catch (UnboundPortException) {
531 #endif //__MEM_PORT_HH__