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