1/* 2 * Copyright (c) 2011-2012 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 <list> 54 55#include "base/range.hh" 56#include "mem/packet.hh" 57 58/** 59 * This typedef is used to clean up getAddrRanges(). It's declared 60 * outside the Port object since it's also used by some mem objects. 61 * Eventually we should move this typedef to wherever Addr is 62 * defined. 63 */ 64 65typedef std::list<Range<Addr> > AddrRangeList; 66typedef std::list<Range<Addr> >::iterator AddrRangeIter; 67 68class MemObject; 69 70/** 71 * Ports are used to interface memory objects to each other. A port is 72 * either a master or a slave and the connected peer is always of the 73 * opposite role. 74 * 75 * Each port has a name and an owner, and enables three basic types of
|
76 * accesses to the peer port: sendFunctional, sendAtomic and
77 * sendTiming.
|
76 * accesses to the peer port: functional, atomic and timing. |
77 */ 78class Port 79{ 80 81 public: 82 83 /** A type name for the port identifier. */ 84 typedef int PortId; 85 86 /** A symbolic name for the absence of a port id. */ 87 static const PortId INVALID_PORT_ID = -1; 88 89 private: 90 91 /** Descriptive name (for DPRINTF output) */ 92 std::string portName; 93 94 protected: 95 96 /** 97 * A numeric identifier to distinguish ports in a vector, and set 98 * to INVALID_PORT_ID in case this port is not part of a vector. 99 */ 100 const PortId id; 101 102 /** A pointer to the peer port. */ 103 Port* peer; 104 105 /** A reference to the MemObject that owns this port. */ 106 MemObject& owner; 107 108 /** 109 * Abstract base class for ports 110 * 111 * @param _name Port name including the owners name 112 * @param _owner The MemObject that is the structural owner of this port 113 * @param _id A port identifier for vector ports 114 */ 115 Port(const std::string& _name, MemObject& _owner, PortId _id); 116 117 /** 118 * Virtual destructor due to inheritance. 119 */ 120 virtual ~Port(); 121 122 public: 123 124 /** Return port name (for DPRINTF). */ 125 const std::string name() const { return portName; } 126 127 /** Get the port id. */ 128 PortId getId() const { return id; } 129 130 protected: 131
|
133 /** These functions are protected because they should only be
134 * called by a peer port, never directly by any outside object. */
135
|
132 /**
|
137 * Receive a timing request or response packet from the peer port.
|
133 * Called by a peer port if sendTimingReq, sendTimingResp or 134 * sendTimingSnoopResp was unsuccesful, and had to wait. |
135 */
|
139 virtual bool recvTiming(PacketPtr pkt) = 0;
140
141 /**
142 * Receive a timing snoop request or snoop response packet from
143 * the peer port.
144 */
145 virtual bool recvTimingSnoop(PacketPtr pkt)
146 {
147 panic("%s was not expecting a timing snoop\n", name());
148 return false;
149 }
150
151 /**
152 * Called by a peer port if sendTiming or sendTimingSnoop was
153 * unsuccesful, and had to wait.
154 */
|
136 virtual void recvRetry() = 0; 137 138 public: 139 140 /**
|
160 * Attempt to send a timing request or response packet to the peer
161 * port by calling its receive function. If the send does not
162 * succeed, as indicated by the return value, then the sender must
163 * wait for a recvRetry at which point it can re-issue a
164 * sendTiming.
165 *
166 * @param pkt Packet to send.
167 *
168 * @return If the send was succesful or not.
169 */
170 bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); }
171
172 /**
173 * Attempt to send a timing snoop request or snoop response packet
174 * to the peer port by calling its receive function. If the send
175 * does not succeed, as indicated by the return value, then the
176 * sender must wait for a recvRetry at which point it can re-issue
177 * a sendTimingSnoop.
178 *
179 * @param pkt Packet to send.
180 *
181 * @return If the send was succesful or not.
182 */
183 bool sendTimingSnoop(PacketPtr pkt) { return peer->recvTimingSnoop(pkt); }
184
185 /**
|
141 * Send a retry to a peer port that previously attempted a
|
187 * sendTiming or sendTimingSnoop which was unsuccessful.
|
142 * sendTimingReq, sendTimingResp or sendTimingSnoopResp which was 143 * unsuccessful. |
144 */ 145 void sendRetry() { return peer->recvRetry(); } 146 147}; 148 149/** Forward declaration */ 150class SlavePort; 151 152/** 153 * A MasterPort is a specialisation of a port. In addition to the 154 * basic functionality of sending packets to its slave peer, it also 155 * has functions specific to a master, e.g. to receive range changes 156 * or determine if the port is snooping or not. 157 */ 158class MasterPort : public Port 159{ 160
|
161 friend class SlavePort; 162 |
163 private: 164 165 SlavePort* _slavePort; 166 167 public: 168 169 MasterPort(const std::string& name, MemObject* owner, 170 PortId id = INVALID_PORT_ID); 171 virtual ~MasterPort(); 172 173 void bind(SlavePort& slave_port); 174 SlavePort& getSlavePort() const; 175 bool isConnected() const; 176 177 /** 178 * Send an atomic request packet, where the data is moved and the 179 * state is updated in zero time, without interleaving with other 180 * memory accesses. 181 * 182 * @param pkt Packet to send. 183 * 184 * @return Estimated latency of access. 185 */ 186 Tick sendAtomic(PacketPtr pkt); 187 188 /** 189 * Send a functional request packet, where the data is instantly 190 * updated everywhere in the memory system, without affecting the 191 * current state of any block or moving the block. 192 * 193 * @param pkt Packet to send. 194 */ 195 void sendFunctional(PacketPtr pkt); 196 197 /**
|
240 * Receive an atomic snoop request packet from the slave port.
241 */
242 virtual Tick recvAtomicSnoop(PacketPtr pkt)
243 {
244 panic("%s was not expecting an atomic snoop\n", name());
245 return 0;
246 }
|
198 * Attempt to send a timing request to the slave port by calling 199 * its corresponding receive function. If the send does not 200 * succeed, as indicated by the return value, then the sender must 201 * wait for a recvRetry at which point it can re-issue a 202 * sendTimingReq. 203 * 204 * @param pkt Packet to send. 205 * 206 * @return If the send was succesful or not. 207 */ 208 bool sendTimingReq(PacketPtr pkt); |
209 210 /**
|
249 * Receive a functional snoop request packet from the slave port.
|
211 * Attempt to send a timing snoop response packet to the slave 212 * port by calling its corresponding receive function. If the send 213 * does not succeed, as indicated by the return value, then the 214 * sender must wait for a recvRetry at which point it can re-issue 215 * a sendTimingSnoopResp. 216 * 217 * @param pkt Packet to send. |
218 */
|
251 virtual void recvFunctionalSnoop(PacketPtr pkt)
252 {
253 panic("%s was not expecting a functional snoop\n", name());
254 }
|
219 bool sendTimingSnoopResp(PacketPtr pkt); |
220 221 /**
|
257 * Called to receive an address range change from the peer slave
258 * port. the default implementation ignored the change and does
259 * nothing. Override this function in a derived class if the owner
260 * needs to be aware of he laesddress ranges, e.g. in an
261 * interconnect component like a bus.
262 */
263 virtual void recvRangeChange() { }
264
265 /**
|
222 * Determine if this master port is snooping or not. The default 223 * implementation returns false and thus tells the neighbour we 224 * are not snooping. Any master port that wants to receive snoop 225 * requests (e.g. a cache connected to a bus) has to override this 226 * function. 227 * 228 * @return true if the port should be considered a snooper 229 */ 230 virtual bool isSnooping() const { return false; } 231 232 /** 233 * Called by a peer port in order to determine the block size of 234 * the owner of this port. 235 */ 236 virtual unsigned deviceBlockSize() const { return 0; } 237 238 /** Called by the associated device if it wishes to find out the blocksize 239 of the device on attached to the peer port. 240 */ 241 unsigned peerBlockSize() const; 242 243 /** Inject a PrintReq for the given address to print the state of 244 * that address throughout the memory system. For debugging. 245 */ 246 void printAddr(Addr a);
|
247 248 protected: 249 250 /** 251 * Receive an atomic snoop request packet from the slave port. 252 */ 253 virtual Tick recvAtomicSnoop(PacketPtr pkt) 254 { 255 panic("%s was not expecting an atomic snoop request\n", name()); 256 return 0; 257 } 258 259 /** 260 * Receive a functional snoop request packet from the slave port. 261 */ 262 virtual void recvFunctionalSnoop(PacketPtr pkt) 263 { 264 panic("%s was not expecting a functional snoop request\n", name()); 265 } 266 267 /** 268 * Receive a timing response from the slave port. 269 */ 270 virtual bool recvTimingResp(PacketPtr pkt) = 0; 271 272 /** 273 * Receive a timing snoop request from the slave port. 274 */ 275 virtual void recvTimingSnoopReq(PacketPtr pkt) 276 { 277 panic("%s was not expecting a timing snoop request\n", name()); 278 } 279 280 /** 281 * Called to receive an address range change from the peer slave 282 * port. the default implementation ignored the change and does 283 * nothing. Override this function in a derived class if the owner 284 * needs to be aware of he laesddress ranges, e.g. in an 285 * interconnect component like a bus. 286 */ 287 virtual void recvRangeChange() { } |
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 */ 296class SlavePort : public Port 297{ 298
|
299 friend class MasterPort; 300 |
301 private: 302 303 MasterPort* _masterPort; 304 305 public: 306 307 SlavePort(const std::string& name, MemObject* owner, 308 PortId id = INVALID_PORT_ID); 309 virtual ~SlavePort(); 310 311 void bind(MasterPort& master_port); 312 MasterPort& getMasterPort() const; 313 bool isConnected() const; 314 315 /** 316 * Send an atomic snoop request packet, where the data is moved 317 * and the state is updated in zero time, without interleaving 318 * with other memory accesses. 319 * 320 * @param pkt Snoop packet to send. 321 * 322 * @return Estimated latency of access. 323 */ 324 Tick sendAtomicSnoop(PacketPtr pkt); 325 326 /** 327 * Send a functional snoop request packet, where the data is 328 * instantly updated everywhere in the memory system, without 329 * affecting the current state of any block or moving the block. 330 * 331 * @param pkt Snoop packet to send. 332 */ 333 void sendFunctionalSnoop(PacketPtr pkt); 334 335 /**
|
337 * Receive an atomic request packet from the master port.
338 */
339 virtual Tick recvAtomic(PacketPtr pkt) = 0;
|
336 * Attempt to send a timing response to the master port by calling 337 * its corresponding receive function. If the send does not 338 * succeed, as indicated by the return value, then the sender must 339 * wait for a recvRetry at which point it can re-issue a 340 * sendTimingResp. 341 * 342 * @param pkt Packet to send. 343 * 344 * @return If the send was succesful or not. 345 */ 346 bool sendTimingResp(PacketPtr pkt); |
347 348 /**
|
342 * Receive a functional request packet from the master port.
|
349 * Attempt to send a timing snoop request packet to the master port 350 * by calling its corresponding receive function. Snoop requests 351 * always succeed and hence no return value is needed. 352 * 353 * @param pkt Packet to send. |
354 */
|
344 virtual void recvFunctional(PacketPtr pkt) = 0;
|
355 void sendTimingSnoopReq(PacketPtr pkt); |
356 357 /** 358 * Called by a peer port in order to determine the block size of 359 * the owner of this port. 360 */ 361 virtual unsigned deviceBlockSize() const { return 0; } 362 363 /** Called by the associated device if it wishes to find out the blocksize 364 of the device on attached to the peer port. 365 */ 366 unsigned peerBlockSize() const; 367 368 /** 369 * Called by the owner to send a range change 370 */ 371 void sendRangeChange() const { _masterPort->recvRangeChange(); } 372 373 /** 374 * Get a list of the non-overlapping address ranges the owner is 375 * responsible for. All slave ports must override this function 376 * and return a populated list with at least one item. 377 * 378 * @return a list of ranges responded to 379 */ 380 virtual AddrRangeList getAddrRanges() = 0;
|
381 382 protected: 383 384 /** 385 * Receive an atomic request packet from the master port. 386 */ 387 virtual Tick recvAtomic(PacketPtr pkt) = 0; 388 389 /** 390 * Receive a functional request packet from the master port. 391 */ 392 virtual void recvFunctional(PacketPtr pkt) = 0; 393 394 /** 395 * Receive a timing request from the master port. 396 */ 397 virtual bool recvTimingReq(PacketPtr pkt) = 0; 398 399 /** 400 * Receive a timing snoop response from the master port. 401 */ 402 virtual bool recvTimingSnoopResp(PacketPtr pkt) 403 { 404 panic("%s was not expecting a timing snoop response\n", name()); 405 } 406 |
407}; 408 409#endif //__MEM_PORT_HH__
|