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