port.hh revision 9294
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/addr_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<AddrRange> AddrRangeList; 66typedef std::list<AddrRange>::iterator AddrRangeIter; 67typedef std::list<AddrRange>::const_iterator AddrRangeConstIter; 68 69class MemObject; 70 71/** 72 * Ports are used to interface memory objects to each other. A port is 73 * either a master or a slave and the connected peer is always of the 74 * opposite role. Each port has a name, an owner, and an identifier. 75 */ 76class Port 77{ 78 79 private: 80 81 /** Descriptive name (for DPRINTF output) */ 82 std::string portName; 83 84 protected: 85 86 /** 87 * A numeric identifier to distinguish ports in a vector, and set 88 * to InvalidPortID in case this port is not part of a vector. 89 */ 90 const PortID id; 91 92 /** A reference to the MemObject that owns this port. */ 93 MemObject& owner; 94 95 /** 96 * Abstract base class for ports 97 * 98 * @param _name Port name including the owners name 99 * @param _owner The MemObject that is the structural owner of this port 100 * @param _id A port identifier for vector ports 101 */ 102 Port(const std::string& _name, MemObject& _owner, PortID _id); 103 104 /** 105 * Virtual destructor due to inheritance. 106 */ 107 virtual ~Port(); 108 109 public: 110 111 /** Return port name (for DPRINTF). */ 112 const std::string name() const { return portName; } 113 114 /** Get the port id. */ 115 PortID getId() const { return id; } 116 117}; 118 119/** Forward declaration */ 120class BaseSlavePort; 121 122/** 123 * A BaseMasterPort is a protocol-agnostic master port, responsible 124 * only for the structural connection to a slave port. The final 125 * master port that inherits from the base class must override the 126 * bind member function for the specific slave port class. 127 */ 128class BaseMasterPort : public Port 129{ 130 131 protected: 132 133 BaseSlavePort* _baseSlavePort; 134 135 BaseMasterPort(const std::string& name, MemObject* owner, 136 PortID id = InvalidPortID); 137 virtual ~BaseMasterPort(); 138 139 public: 140 141 virtual void bind(BaseSlavePort& slave_port) = 0; 142 virtual void unbind() = 0; 143 BaseSlavePort& getSlavePort() const; 144 bool isConnected() const; 145 146}; 147 148/** 149 * A BaseSlavePort is a protocol-agnostic slave port, responsible 150 * only for the structural connection to a master port. 151 */ 152class BaseSlavePort : public Port 153{ 154 155 protected: 156 157 BaseMasterPort* _baseMasterPort; 158 159 BaseSlavePort(const std::string& name, MemObject* owner, 160 PortID id = InvalidPortID); 161 virtual ~BaseSlavePort(); 162 163 public: 164 165 BaseMasterPort& getMasterPort() const; 166 bool isConnected() const; 167 168}; 169 170/** Forward declaration */ 171class SlavePort; 172 173/** 174 * A MasterPort is a specialisation of a BaseMasterPort, which 175 * implements the default protocol for the three different level of 176 * transport functions. In addition to the basic functionality of 177 * sending packets, it also has functions to receive range changes or 178 * determine if the port is snooping or not. 179 */ 180class MasterPort : public BaseMasterPort 181{ 182 183 friend class SlavePort; 184 185 private: 186 187 SlavePort* _slavePort; 188 189 public: 190 191 MasterPort(const std::string& name, MemObject* owner, 192 PortID id = InvalidPortID); 193 virtual ~MasterPort(); 194 195 /** 196 * Bind this master port to a slave port. This also does the 197 * mirror action and binds the slave port to the master port. 198 */ 199 void bind(BaseSlavePort& slave_port); 200 201 /** 202 * Unbind this master port and the associated slave port. 203 */ 204 void unbind(); 205 206 /** 207 * Send an atomic request packet, where the data is moved and the 208 * state is updated in zero time, without interleaving with other 209 * memory accesses. 210 * 211 * @param pkt Packet to send. 212 * 213 * @return Estimated latency of access. 214 */ 215 Tick sendAtomic(PacketPtr pkt); 216 217 /** 218 * Send a functional request packet, where the data is instantly 219 * updated everywhere in the memory system, without affecting the 220 * current state of any block or moving the block. 221 * 222 * @param pkt Packet to send. 223 */ 224 void sendFunctional(PacketPtr pkt); 225 226 /** 227 * Attempt to send a timing request to the slave port by calling 228 * its corresponding receive function. If the send does not 229 * succeed, as indicated by the return value, then the sender must 230 * wait for a recvRetry at which point it can re-issue a 231 * sendTimingReq. 232 * 233 * @param pkt Packet to send. 234 * 235 * @return If the send was succesful or not. 236 */ 237 bool sendTimingReq(PacketPtr pkt); 238 239 /** 240 * Attempt to send a timing snoop response packet to the slave 241 * port by calling its corresponding receive function. If the send 242 * does not succeed, as indicated by the return value, then the 243 * sender must wait for a recvRetry at which point it can re-issue 244 * a sendTimingSnoopResp. 245 * 246 * @param pkt Packet to send. 247 */ 248 bool sendTimingSnoopResp(PacketPtr pkt); 249 250 /** 251 * Send a retry to the slave port that previously attempted a 252 * sendTimingResp to this master port and failed. 253 */ 254 void sendRetry(); 255 256 /** 257 * Determine if this master port is snooping or not. The default 258 * implementation returns false and thus tells the neighbour we 259 * are not snooping. Any master port that wants to receive snoop 260 * requests (e.g. a cache connected to a bus) has to override this 261 * function. 262 * 263 * @return true if the port should be considered a snooper 264 */ 265 virtual bool isSnooping() const { return false; } 266 267 /** 268 * Called by a peer port in order to determine the block size of 269 * the owner of this port. 270 */ 271 virtual unsigned deviceBlockSize() const { return 0; } 272 273 /** Called by the associated device if it wishes to find out the blocksize 274 of the device on attached to the peer port. 275 */ 276 unsigned peerBlockSize() const; 277 278 /** 279 * Get the address ranges of the connected slave port. 280 */ 281 AddrRangeList getAddrRanges() const; 282 283 /** Inject a PrintReq for the given address to print the state of 284 * that address throughout the memory system. For debugging. 285 */ 286 void printAddr(Addr a); 287 288 protected: 289 290 /** 291 * Receive an atomic snoop request packet from the slave port. 292 */ 293 virtual Tick recvAtomicSnoop(PacketPtr pkt) 294 { 295 panic("%s was not expecting an atomic snoop request\n", name()); 296 return 0; 297 } 298 299 /** 300 * Receive a functional snoop request packet from the slave port. 301 */ 302 virtual void recvFunctionalSnoop(PacketPtr pkt) 303 { 304 panic("%s was not expecting a functional snoop request\n", name()); 305 } 306 307 /** 308 * Receive a timing response from the slave port. 309 */ 310 virtual bool recvTimingResp(PacketPtr pkt) = 0; 311 312 /** 313 * Receive a timing snoop request from the slave port. 314 */ 315 virtual void recvTimingSnoopReq(PacketPtr pkt) 316 { 317 panic("%s was not expecting a timing snoop request\n", name()); 318 } 319 320 /** 321 * Called by the slave port if sendTimingReq or 322 * sendTimingSnoopResp was called on this master port (causing 323 * recvTimingReq and recvTimingSnoopResp to be called on the 324 * slave port) and was unsuccesful. 325 */ 326 virtual void recvRetry() = 0; 327 328 /** 329 * Called to receive an address range change from the peer slave 330 * port. the default implementation ignored the change and does 331 * nothing. Override this function in a derived class if the owner 332 * needs to be aware of he laesddress ranges, e.g. in an 333 * interconnect component like a bus. 334 */ 335 virtual void recvRangeChange() { } 336}; 337 338/** 339 * A SlavePort is a specialisation of a port. In addition to the 340 * basic functionality of sending packets to its master peer, it also 341 * has functions specific to a slave, e.g. to send range changes 342 * and get the address ranges that the port responds to. 343 */ 344class SlavePort : public BaseSlavePort 345{ 346 347 friend class MasterPort; 348 349 private: 350 351 MasterPort* _masterPort; 352 353 public: 354 355 SlavePort(const std::string& name, MemObject* owner, 356 PortID id = InvalidPortID); 357 virtual ~SlavePort(); 358 359 /** 360 * Send an atomic snoop request packet, where the data is moved 361 * and the state is updated in zero time, without interleaving 362 * with other memory accesses. 363 * 364 * @param pkt Snoop packet to send. 365 * 366 * @return Estimated latency of access. 367 */ 368 Tick sendAtomicSnoop(PacketPtr pkt); 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 sendFunctionalSnoop(PacketPtr pkt); 378 379 /** 380 * Attempt to send a timing response to the master port by calling 381 * its corresponding receive function. If the send does not 382 * succeed, as indicated by the return value, then the sender must 383 * wait for a recvRetry at which point it can re-issue a 384 * sendTimingResp. 385 * 386 * @param pkt Packet to send. 387 * 388 * @return If the send was succesful or not. 389 */ 390 bool sendTimingResp(PacketPtr pkt); 391 392 /** 393 * Attempt to send a timing snoop request packet to the master port 394 * by calling its corresponding receive function. Snoop requests 395 * always succeed and hence no return value is needed. 396 * 397 * @param pkt Packet to send. 398 */ 399 void sendTimingSnoopReq(PacketPtr pkt); 400 401 /** 402 * Send a retry to the master port that previously attempted a 403 * sendTimingReq or sendTimingSnoopResp to this slave port and 404 * failed. 405 */ 406 void sendRetry(); 407 408 /** 409 * Called by a peer port in order to determine the block size of 410 * the owner of this port. 411 */ 412 virtual unsigned deviceBlockSize() const { return 0; } 413 414 /** Called by the associated device if it wishes to find out the blocksize 415 of the device on attached to the peer port. 416 */ 417 unsigned peerBlockSize() const; 418 419 /** 420 * Find out if the peer master port is snooping or not. 421 * 422 * @return true if the peer master port is snooping 423 */ 424 bool isSnooping() const { return _masterPort->isSnooping(); } 425 426 /** 427 * Called by the owner to send a range change 428 */ 429 void sendRangeChange() const { _masterPort->recvRangeChange(); } 430 431 /** 432 * Get a list of the non-overlapping address ranges the owner is 433 * responsible for. All slave ports must override this function 434 * and return a populated list with at least one item. 435 * 436 * @return a list of ranges responded to 437 */ 438 virtual AddrRangeList getAddrRanges() const = 0; 439 440 protected: 441 442 /** 443 * Called by the master port to unbind. Should never be called 444 * directly. 445 */ 446 void unbind(); 447 448 /** 449 * Called by the master port to bind. Should never be called 450 * directly. 451 */ 452 void bind(MasterPort& master_port); 453 454 /** 455 * Receive an atomic request packet from the master port. 456 */ 457 virtual Tick recvAtomic(PacketPtr pkt) = 0; 458 459 /** 460 * Receive a functional request packet from the master port. 461 */ 462 virtual void recvFunctional(PacketPtr pkt) = 0; 463 464 /** 465 * Receive a timing request from the master port. 466 */ 467 virtual bool recvTimingReq(PacketPtr pkt) = 0; 468 469 /** 470 * Receive a timing snoop response from the master port. 471 */ 472 virtual bool recvTimingSnoopResp(PacketPtr pkt) 473 { 474 panic("%s was not expecting a timing snoop response\n", name()); 475 } 476 477 /** 478 * Called by the master port if sendTimingResp was called on this 479 * slave port (causing recvTimingResp to be called on the master 480 * port) and was unsuccesful. 481 */ 482 virtual void recvRetry() = 0; 483 484}; 485 486#endif //__MEM_PORT_HH__ 487