port.hh revision 5476
12381SN/A/* 22381SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32381SN/A * All rights reserved. 42381SN/A * 52381SN/A * Redistribution and use in source and binary forms, with or without 62381SN/A * modification, are permitted provided that the following conditions are 72381SN/A * met: redistributions of source code must retain the above copyright 82381SN/A * notice, this list of conditions and the following disclaimer; 92381SN/A * redistributions in binary form must reproduce the above copyright 102381SN/A * notice, this list of conditions and the following disclaimer in the 112381SN/A * documentation and/or other materials provided with the distribution; 122381SN/A * neither the name of the copyright holders nor the names of its 132381SN/A * contributors may be used to endorse or promote products derived from 142381SN/A * this software without specific prior written permission. 152381SN/A * 162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292381SN/A */ 302381SN/A 312381SN/A/** 322381SN/A * @file 332982Sstever@eecs.umich.edu * Port Object Declaration. Ports are used to interface memory objects to 342381SN/A * each other. They will always come in pairs, and we refer to the other 352381SN/A * port object as the peer. These are used to make the design more 362381SN/A * modular so that a specific interface between every type of objcet doesn't 372381SN/A * have to be created. 382381SN/A */ 392381SN/A 402381SN/A#ifndef __MEM_PORT_HH__ 412381SN/A#define __MEM_PORT_HH__ 422381SN/A 432381SN/A#include <list> 442381SN/A#include <inttypes.h> 452381SN/A 462439SN/A#include "base/misc.hh" 472381SN/A#include "base/range.hh" 482381SN/A#include "mem/packet.hh" 492381SN/A#include "mem/request.hh" 502381SN/A 512407SN/A/** This typedef is used to clean up the parameter list of 522407SN/A * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared 532407SN/A * outside the Port object since it's also used by some mem objects. 542407SN/A * Eventually we should move this typedef to wherever Addr is 552407SN/A * defined. 562407SN/A */ 572407SN/A 582407SN/Atypedef std::list<Range<Addr> > AddrRangeList; 592521SN/Atypedef std::list<Range<Addr> >::iterator AddrRangeIter; 602407SN/A 613401Sktlim@umich.educlass MemObject; 623401Sktlim@umich.edu 632381SN/A/** 642381SN/A * Ports are used to interface memory objects to 652381SN/A * each other. They will always come in pairs, and we refer to the other 662381SN/A * port object as the peer. These are used to make the design more 672381SN/A * modular so that a specific interface between every type of objcet doesn't 682381SN/A * have to be created. 692381SN/A * 702381SN/A * Recv accesor functions are being called from the peer interface. 712381SN/A * Send accessor functions are being called from the device the port is 722381SN/A * associated with, and it will call the peer recv. accessor function. 732381SN/A */ 742381SN/Aclass Port 752381SN/A{ 765476Snate@binkert.org protected: 772640Sstever@eecs.umich.edu /** Descriptive name (for DPRINTF output) */ 782796Sktlim@umich.edu mutable std::string portName; 792640Sstever@eecs.umich.edu 802661Sstever@eecs.umich.edu /** A pointer to the peer port. Ports always come in pairs, that way they 812661Sstever@eecs.umich.edu can use a standardized interface to communicate between different 822661Sstever@eecs.umich.edu memory objects. */ 832661Sstever@eecs.umich.edu Port *peer; 842661Sstever@eecs.umich.edu 853401Sktlim@umich.edu /** A pointer to the MemObject that owns this port. This may not be set. */ 863401Sktlim@umich.edu MemObject *owner; 873401Sktlim@umich.edu 882381SN/A public: 892381SN/A 905283Sgblack@eecs.umich.edu Port(); 912796Sktlim@umich.edu 922640Sstever@eecs.umich.edu /** 932640Sstever@eecs.umich.edu * Constructor. 942640Sstever@eecs.umich.edu * 952640Sstever@eecs.umich.edu * @param _name Port name for DPRINTF output. Should include name 962640Sstever@eecs.umich.edu * of memory system object to which the port belongs. 973401Sktlim@umich.edu * @param _owner Pointer to the MemObject that owns this port. 983401Sktlim@umich.edu * Will not necessarily be set. 992640Sstever@eecs.umich.edu */ 1005283Sgblack@eecs.umich.edu Port(const std::string &_name, MemObject *_owner = NULL); 1012640Sstever@eecs.umich.edu 1022640Sstever@eecs.umich.edu /** Return port name (for DPRINTF). */ 1032640Sstever@eecs.umich.edu const std::string &name() const { return portName; } 1042640Sstever@eecs.umich.edu 1055476Snate@binkert.org virtual ~Port(); 1062640Sstever@eecs.umich.edu 1072381SN/A // mey be better to use subclasses & RTTI? 1082657Ssaidi@eecs.umich.edu /** Holds the ports status. Currently just that a range recomputation needs 1092657Ssaidi@eecs.umich.edu * to be done. */ 1102381SN/A enum Status { 1113173Srdreslin@umich.edu RangeChange 1122381SN/A }; 1132381SN/A 1142796Sktlim@umich.edu void setName(const std::string &name) 1152796Sktlim@umich.edu { portName = name; } 1162796Sktlim@umich.edu 1173401Sktlim@umich.edu /** Function to set the pointer for the peer port. */ 1184192Sktlim@umich.edu virtual void setPeer(Port *port); 1192381SN/A 1203401Sktlim@umich.edu /** Function to get the pointer to the peer port. */ 1212409SN/A Port *getPeer() { return peer; } 1222408SN/A 1233401Sktlim@umich.edu /** Function to set the owner of this port. */ 1243401Sktlim@umich.edu void setOwner(MemObject *_owner) { owner = _owner; } 1253401Sktlim@umich.edu 1263401Sktlim@umich.edu /** Function to return the owner of this port. */ 1273401Sktlim@umich.edu MemObject *getOwner() { return owner; } 1283401Sktlim@umich.edu 1294190Ssaidi@eecs.umich.edu /** Inform the peer port to delete itself and notify it's owner about it's 1304190Ssaidi@eecs.umich.edu * demise. */ 1314190Ssaidi@eecs.umich.edu void removeConn(); 1324190Ssaidi@eecs.umich.edu 1335476Snate@binkert.org virtual bool isDefaultPort() const { return false; } 1345476Snate@binkert.org 1355476Snate@binkert.org bool isConnected() { return peer && !peer->isDefaultPort(); } 1364190Ssaidi@eecs.umich.edu 1372381SN/A protected: 1382381SN/A 1392406SN/A /** These functions are protected because they should only be 1402406SN/A * called by a peer port, never directly by any outside object. */ 1412406SN/A 1422381SN/A /** Called to recive a timing call from the peer port. */ 1433349Sbinkertn@umich.edu virtual bool recvTiming(PacketPtr pkt) = 0; 1442381SN/A 1452381SN/A /** Called to recive a atomic call from the peer port. */ 1463349Sbinkertn@umich.edu virtual Tick recvAtomic(PacketPtr pkt) = 0; 1472381SN/A 1482381SN/A /** Called to recive a functional call from the peer port. */ 1493349Sbinkertn@umich.edu virtual void recvFunctional(PacketPtr pkt) = 0; 1502381SN/A 1512381SN/A /** Called to recieve a status change from the peer port. */ 1522381SN/A virtual void recvStatusChange(Status status) = 0; 1532381SN/A 1542381SN/A /** Called by a peer port if the send was unsuccesful, and had to 1552381SN/A wait. This shouldn't be valid for response paths (IO Devices). 1562381SN/A so it is set to panic if it isn't already defined. 1572381SN/A */ 1582657Ssaidi@eecs.umich.edu virtual void recvRetry() { panic("??"); } 1592381SN/A 1602381SN/A /** Called by a peer port in order to determine the block size of the 1612381SN/A device connected to this port. It sometimes doesn't make sense for 1624432Ssaidi@eecs.umich.edu this function to be called, so it just returns 0. Anytthing that is 1634432Ssaidi@eecs.umich.edu concerned with the size should just ignore that. 1642381SN/A */ 1654432Ssaidi@eecs.umich.edu virtual int deviceBlockSize() { return 0; } 1662381SN/A 1672381SN/A /** The peer port is requesting us to reply with a list of the ranges we 1682381SN/A are responsible for. 1692521SN/A @param resp is a list of ranges responded to 1702521SN/A @param snoop is a list of ranges snooped 1712381SN/A */ 1722521SN/A virtual void getDeviceAddressRanges(AddrRangeList &resp, 1734475Sstever@eecs.umich.edu bool &snoop) 1742407SN/A { panic("??"); } 1752381SN/A 1762381SN/A public: 1772381SN/A 1782381SN/A /** Function called by associated memory device (cache, memory, iodevice) 1792381SN/A in order to send a timing request to the port. Simply calls the peer 1802381SN/A port receive function. 1812381SN/A @return This function returns if the send was succesful in it's 1822381SN/A recieve. If it was a failure, then the port will wait for a recvRetry 1832657Ssaidi@eecs.umich.edu at which point it can possibly issue a successful sendTiming. This is used in 1842381SN/A case a cache has a higher priority request come in while waiting for 1852381SN/A the bus to arbitrate. 1862381SN/A */ 1873349Sbinkertn@umich.edu bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } 1882381SN/A 1892662Sstever@eecs.umich.edu /** Function called by the associated device to send an atomic 1902662Sstever@eecs.umich.edu * access, an access in which the data is moved and the state is 1912662Sstever@eecs.umich.edu * updated in one cycle, without interleaving with other memory 1922662Sstever@eecs.umich.edu * accesses. Returns estimated latency of access. 1932662Sstever@eecs.umich.edu */ 1943349Sbinkertn@umich.edu Tick sendAtomic(PacketPtr pkt) 1952381SN/A { return peer->recvAtomic(pkt); } 1962381SN/A 1972381SN/A /** Function called by the associated device to send a functional access, 1982381SN/A an access in which the data is instantly updated everywhere in the 1992520SN/A memory system, without affecting the current state of any block or 2002520SN/A moving the block. 2012381SN/A */ 2023349Sbinkertn@umich.edu void sendFunctional(PacketPtr pkt) 2032381SN/A { return peer->recvFunctional(pkt); } 2042381SN/A 2052381SN/A /** Called by the associated device to send a status change to the device 2062381SN/A connected to the peer interface. 2072381SN/A */ 2082381SN/A void sendStatusChange(Status status) {peer->recvStatusChange(status); } 2092381SN/A 2102381SN/A /** When a timing access doesn't return a success, some time later the 2112381SN/A Retry will be sent. 2122381SN/A */ 2132657Ssaidi@eecs.umich.edu void sendRetry() { return peer->recvRetry(); } 2142381SN/A 2152381SN/A /** Called by the associated device if it wishes to find out the blocksize 2162381SN/A of the device on attached to the peer port. 2172381SN/A */ 2182406SN/A int peerBlockSize() { return peer->deviceBlockSize(); } 2192381SN/A 2202381SN/A /** Called by the associated device if it wishes to find out the address 2212381SN/A ranges connected to the peer ports devices. 2222381SN/A */ 2234475Sstever@eecs.umich.edu void getPeerAddressRanges(AddrRangeList &resp, bool &snoop) 2242521SN/A { peer->getDeviceAddressRanges(resp, snoop); } 2252381SN/A 2262461SN/A /** This function is a wrapper around sendFunctional() 2272461SN/A that breaks a larger, arbitrarily aligned access into 2282461SN/A appropriate chunks. The default implementation can use 2292461SN/A getBlockSize() to determine the block size and go from there. 2302461SN/A */ 2312519SN/A virtual void readBlob(Addr addr, uint8_t *p, int size); 2322381SN/A 2332381SN/A /** This function is a wrapper around sendFunctional() 2342381SN/A that breaks a larger, arbitrarily aligned access into 2352381SN/A appropriate chunks. The default implementation can use 2362381SN/A getBlockSize() to determine the block size and go from there. 2372381SN/A */ 2382519SN/A virtual void writeBlob(Addr addr, uint8_t *p, int size); 2392381SN/A 2402381SN/A /** Fill size bytes starting at addr with byte value val. This 2412381SN/A should not need to be virtual, since it can be implemented in 2422461SN/A terms of writeBlob(). However, it shouldn't be 2432381SN/A performance-critical either, so it could be if we wanted to. 2442381SN/A */ 2452519SN/A virtual void memsetBlob(Addr addr, uint8_t val, int size); 2462405SN/A 2475314Sstever@gmail.com /** Inject a PrintReq for the given address to print the state of 2485314Sstever@gmail.com * that address throughout the memory system. For debugging. 2495314Sstever@gmail.com */ 2505314Sstever@gmail.com void printAddr(Addr a); 2515314Sstever@gmail.com 2522405SN/A private: 2532405SN/A 2542405SN/A /** Internal helper function for read/writeBlob(). 2552405SN/A */ 2564022Sstever@eecs.umich.edu void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); 2572381SN/A}; 2582381SN/A 2592520SN/A/** A simple functional port that is only meant for one way communication to 2602520SN/A * physical memory. It is only meant to be used to load data into memory before 2612520SN/A * the simulation begins. 2622520SN/A */ 2632520SN/A 2642520SN/Aclass FunctionalPort : public Port 2652520SN/A{ 2662520SN/A public: 2673401Sktlim@umich.edu FunctionalPort(const std::string &_name, MemObject *_owner = NULL) 2683401Sktlim@umich.edu : Port(_name, _owner) 2692640Sstever@eecs.umich.edu {} 2702640Sstever@eecs.umich.edu 2713091Sstever@eecs.umich.edu protected: 2723918Ssaidi@eecs.umich.edu virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); 2733918Ssaidi@eecs.umich.edu M5_DUMMY_RETURN } 2743918Ssaidi@eecs.umich.edu virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); 2753918Ssaidi@eecs.umich.edu M5_DUMMY_RETURN } 2763349Sbinkertn@umich.edu virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); } 2772590SN/A virtual void recvStatusChange(Status status) {} 2782521SN/A 2793091Sstever@eecs.umich.edu public: 2802684Ssaidi@eecs.umich.edu /** a write function that also does an endian conversion. */ 2812684Ssaidi@eecs.umich.edu template <typename T> 2822684Ssaidi@eecs.umich.edu inline void writeHtoG(Addr addr, T d); 2832684Ssaidi@eecs.umich.edu 2842684Ssaidi@eecs.umich.edu /** a read function that also does an endian conversion. */ 2852684Ssaidi@eecs.umich.edu template <typename T> 2862684Ssaidi@eecs.umich.edu inline T readGtoH(Addr addr); 2872684Ssaidi@eecs.umich.edu 2882521SN/A template <typename T> 2892521SN/A inline void write(Addr addr, T d) 2902521SN/A { 2912521SN/A writeBlob(addr, (uint8_t*)&d, sizeof(T)); 2922521SN/A } 2932521SN/A 2942521SN/A template <typename T> 2952521SN/A inline T read(Addr addr) 2962521SN/A { 2972521SN/A T d; 2982521SN/A readBlob(addr, (uint8_t*)&d, sizeof(T)); 2992521SN/A return d; 3002521SN/A } 3012520SN/A}; 3022520SN/A 3032381SN/A#endif //__MEM_PORT_HH__ 304