port.hh revision 2641:6d9d837e2032
112027Sjungma@eit.uni-kl.de/* 212027Sjungma@eit.uni-kl.de * Copyright (c) 2002-2005 The Regents of The University of Michigan 312027Sjungma@eit.uni-kl.de * All rights reserved. 412027Sjungma@eit.uni-kl.de * 512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without 612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are 712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright 812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer; 912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright 1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the 1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution; 1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its 1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from 1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission. 1512027Sjungma@eit.uni-kl.de * 1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712027Sjungma@eit.uni-kl.de */ 2812027Sjungma@eit.uni-kl.de 2912027Sjungma@eit.uni-kl.de/** 3012027Sjungma@eit.uni-kl.de * @file 3112027Sjungma@eit.uni-kl.de * Port Object Decleration. Ports are used to interface memory objects to 3212027Sjungma@eit.uni-kl.de * each other. They will always come in pairs, and we refer to the other 3312027Sjungma@eit.uni-kl.de * port object as the peer. These are used to make the design more 3412027Sjungma@eit.uni-kl.de * modular so that a specific interface between every type of objcet doesn't 3512027Sjungma@eit.uni-kl.de * have to be created. 3612027Sjungma@eit.uni-kl.de */ 3712027Sjungma@eit.uni-kl.de 3812027Sjungma@eit.uni-kl.de#ifndef __MEM_PORT_HH__ 3912027Sjungma@eit.uni-kl.de#define __MEM_PORT_HH__ 4012027Sjungma@eit.uni-kl.de 4112027Sjungma@eit.uni-kl.de#include <list> 4212027Sjungma@eit.uni-kl.de#include <inttypes.h> 4312027Sjungma@eit.uni-kl.de 4412027Sjungma@eit.uni-kl.de#include "base/misc.hh" 4512027Sjungma@eit.uni-kl.de#include "base/range.hh" 4612027Sjungma@eit.uni-kl.de#include "mem/packet.hh" 4712027Sjungma@eit.uni-kl.de#include "mem/request.hh" 4812027Sjungma@eit.uni-kl.de 4912027Sjungma@eit.uni-kl.de/** This typedef is used to clean up the parameter list of 5012027Sjungma@eit.uni-kl.de * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared 5112027Sjungma@eit.uni-kl.de * outside the Port object since it's also used by some mem objects. 5212027Sjungma@eit.uni-kl.de * Eventually we should move this typedef to wherever Addr is 5312027Sjungma@eit.uni-kl.de * defined. 5412027Sjungma@eit.uni-kl.de */ 5512027Sjungma@eit.uni-kl.de 5612027Sjungma@eit.uni-kl.detypedef std::list<Range<Addr> > AddrRangeList; 5712027Sjungma@eit.uni-kl.detypedef std::list<Range<Addr> >::iterator AddrRangeIter; 5812027Sjungma@eit.uni-kl.de 5912027Sjungma@eit.uni-kl.de/** 6012027Sjungma@eit.uni-kl.de * Ports are used to interface memory objects to 6112027Sjungma@eit.uni-kl.de * each other. They will always come in pairs, and we refer to the other 6212027Sjungma@eit.uni-kl.de * port object as the peer. These are used to make the design more 6312027Sjungma@eit.uni-kl.de * modular so that a specific interface between every type of objcet doesn't 6412027Sjungma@eit.uni-kl.de * have to be created. 6512027Sjungma@eit.uni-kl.de * 6612027Sjungma@eit.uni-kl.de * Recv accesor functions are being called from the peer interface. 6712027Sjungma@eit.uni-kl.de * Send accessor functions are being called from the device the port is 6812027Sjungma@eit.uni-kl.de * associated with, and it will call the peer recv. accessor function. 6912027Sjungma@eit.uni-kl.de */ 7012027Sjungma@eit.uni-kl.declass Port 7112027Sjungma@eit.uni-kl.de{ 7212027Sjungma@eit.uni-kl.de private: 7312027Sjungma@eit.uni-kl.de 7412027Sjungma@eit.uni-kl.de /** Descriptive name (for DPRINTF output) */ 7512027Sjungma@eit.uni-kl.de const std::string portName; 7612027Sjungma@eit.uni-kl.de 7712027Sjungma@eit.uni-kl.de public: 7812027Sjungma@eit.uni-kl.de 7912027Sjungma@eit.uni-kl.de /** 8012027Sjungma@eit.uni-kl.de * Constructor. 8112027Sjungma@eit.uni-kl.de * 8212027Sjungma@eit.uni-kl.de * @param _name Port name for DPRINTF output. Should include name 8312027Sjungma@eit.uni-kl.de * of memory system object to which the port belongs. 8412027Sjungma@eit.uni-kl.de */ 8512027Sjungma@eit.uni-kl.de Port(const std::string &_name) 8612027Sjungma@eit.uni-kl.de : portName(_name) 8712027Sjungma@eit.uni-kl.de { } 8812027Sjungma@eit.uni-kl.de 8912027Sjungma@eit.uni-kl.de /** Return port name (for DPRINTF). */ 9012027Sjungma@eit.uni-kl.de const std::string &name() const { return portName; } 9112027Sjungma@eit.uni-kl.de 9212027Sjungma@eit.uni-kl.de virtual ~Port() {}; 9312027Sjungma@eit.uni-kl.de 9412027Sjungma@eit.uni-kl.de // mey be better to use subclasses & RTTI? 9512027Sjungma@eit.uni-kl.de /** Holds the ports status. Keeps track if it is blocked, or has 9612027Sjungma@eit.uni-kl.de calculated a range change. */ 9712027Sjungma@eit.uni-kl.de enum Status { 9812027Sjungma@eit.uni-kl.de Blocked, 9912027Sjungma@eit.uni-kl.de Unblocked, 10012027Sjungma@eit.uni-kl.de RangeChange 10112027Sjungma@eit.uni-kl.de }; 10212027Sjungma@eit.uni-kl.de 10312027Sjungma@eit.uni-kl.de private: 10412027Sjungma@eit.uni-kl.de 10512027Sjungma@eit.uni-kl.de /** A pointer to the peer port. Ports always come in pairs, that way they 10612027Sjungma@eit.uni-kl.de can use a standardized interface to communicate between different 10712027Sjungma@eit.uni-kl.de memory objects. */ 10812027Sjungma@eit.uni-kl.de Port *peer; 10912027Sjungma@eit.uni-kl.de 11012027Sjungma@eit.uni-kl.de public: 11112027Sjungma@eit.uni-kl.de 11212027Sjungma@eit.uni-kl.de /** Function to set the pointer for the peer port. 11312027Sjungma@eit.uni-kl.de @todo should be called by the configuration stuff (python). 11412027Sjungma@eit.uni-kl.de */ 11512027Sjungma@eit.uni-kl.de void setPeer(Port *port) { peer = port; } 11612027Sjungma@eit.uni-kl.de 11712027Sjungma@eit.uni-kl.de /** Function to set the pointer for the peer port. 11812027Sjungma@eit.uni-kl.de @todo should be called by the configuration stuff (python). 11912027Sjungma@eit.uni-kl.de */ 12012027Sjungma@eit.uni-kl.de Port *getPeer() { return peer; } 12112027Sjungma@eit.uni-kl.de 12212027Sjungma@eit.uni-kl.de protected: 12312027Sjungma@eit.uni-kl.de 12412027Sjungma@eit.uni-kl.de /** These functions are protected because they should only be 12512027Sjungma@eit.uni-kl.de * called by a peer port, never directly by any outside object. */ 12612027Sjungma@eit.uni-kl.de 12712027Sjungma@eit.uni-kl.de /** Called to recive a timing call from the peer port. */ 12812027Sjungma@eit.uni-kl.de virtual bool recvTiming(Packet *pkt) = 0; 12912027Sjungma@eit.uni-kl.de 13012027Sjungma@eit.uni-kl.de /** Called to recive a atomic call from the peer port. */ 13112027Sjungma@eit.uni-kl.de virtual Tick recvAtomic(Packet *pkt) = 0; 13212027Sjungma@eit.uni-kl.de 13312027Sjungma@eit.uni-kl.de /** Called to recive a functional call from the peer port. */ 13412027Sjungma@eit.uni-kl.de virtual void recvFunctional(Packet *pkt) = 0; 13512027Sjungma@eit.uni-kl.de 13612027Sjungma@eit.uni-kl.de /** Called to recieve a status change from the peer port. */ 13712027Sjungma@eit.uni-kl.de virtual void recvStatusChange(Status status) = 0; 13812027Sjungma@eit.uni-kl.de 13912027Sjungma@eit.uni-kl.de /** Called by a peer port if the send was unsuccesful, and had to 14012027Sjungma@eit.uni-kl.de wait. This shouldn't be valid for response paths (IO Devices). 14112027Sjungma@eit.uni-kl.de so it is set to panic if it isn't already defined. 14212027Sjungma@eit.uni-kl.de */ 14312027Sjungma@eit.uni-kl.de virtual Packet *recvRetry() { panic("??"); } 14412027Sjungma@eit.uni-kl.de 14512027Sjungma@eit.uni-kl.de /** Called by a peer port in order to determine the block size of the 14612027Sjungma@eit.uni-kl.de device connected to this port. It sometimes doesn't make sense for 14712027Sjungma@eit.uni-kl.de this function to be called, a DMA interface doesn't really have a 14812027Sjungma@eit.uni-kl.de block size, so it is defaulted to a panic. 14912027Sjungma@eit.uni-kl.de */ 15012027Sjungma@eit.uni-kl.de virtual int deviceBlockSize() { panic("??"); } 15112027Sjungma@eit.uni-kl.de 15212027Sjungma@eit.uni-kl.de /** The peer port is requesting us to reply with a list of the ranges we 15312027Sjungma@eit.uni-kl.de are responsible for. 15412027Sjungma@eit.uni-kl.de @param resp is a list of ranges responded to 15512027Sjungma@eit.uni-kl.de @param snoop is a list of ranges snooped 15612027Sjungma@eit.uni-kl.de */ 15712027Sjungma@eit.uni-kl.de virtual void getDeviceAddressRanges(AddrRangeList &resp, 15812027Sjungma@eit.uni-kl.de AddrRangeList &snoop) 15912027Sjungma@eit.uni-kl.de { panic("??"); } 16012027Sjungma@eit.uni-kl.de 16112027Sjungma@eit.uni-kl.de public: 16212027Sjungma@eit.uni-kl.de 16312027Sjungma@eit.uni-kl.de /** Function called by associated memory device (cache, memory, iodevice) 16412027Sjungma@eit.uni-kl.de in order to send a timing request to the port. Simply calls the peer 16512027Sjungma@eit.uni-kl.de port receive function. 16612027Sjungma@eit.uni-kl.de @return This function returns if the send was succesful in it's 16712027Sjungma@eit.uni-kl.de recieve. If it was a failure, then the port will wait for a recvRetry 16812027Sjungma@eit.uni-kl.de at which point it can issue a successful sendTiming. This is used in 16912027Sjungma@eit.uni-kl.de case a cache has a higher priority request come in while waiting for 17012027Sjungma@eit.uni-kl.de the bus to arbitrate. 17112027Sjungma@eit.uni-kl.de */ 17212027Sjungma@eit.uni-kl.de bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); } 17312027Sjungma@eit.uni-kl.de 17412027Sjungma@eit.uni-kl.de /** Function called by the associated device to send an atomic access, 17512027Sjungma@eit.uni-kl.de an access in which the data is moved and the state is updated in one 17612027Sjungma@eit.uni-kl.de cycle, without interleaving with other memory accesses. 17712027Sjungma@eit.uni-kl.de */ 17812027Sjungma@eit.uni-kl.de Tick sendAtomic(Packet *pkt) 17912027Sjungma@eit.uni-kl.de { return peer->recvAtomic(pkt); } 18012027Sjungma@eit.uni-kl.de 18112027Sjungma@eit.uni-kl.de /** Function called by the associated device to send a functional access, 18212027Sjungma@eit.uni-kl.de an access in which the data is instantly updated everywhere in the 18312027Sjungma@eit.uni-kl.de memory system, without affecting the current state of any block or 18412027Sjungma@eit.uni-kl.de moving the block. 18512027Sjungma@eit.uni-kl.de */ 18612027Sjungma@eit.uni-kl.de void sendFunctional(Packet *pkt) 18712027Sjungma@eit.uni-kl.de { return peer->recvFunctional(pkt); } 18812027Sjungma@eit.uni-kl.de 18912027Sjungma@eit.uni-kl.de /** Called by the associated device to send a status change to the device 19012027Sjungma@eit.uni-kl.de connected to the peer interface. 19112027Sjungma@eit.uni-kl.de */ 19212027Sjungma@eit.uni-kl.de void sendStatusChange(Status status) {peer->recvStatusChange(status); } 19312027Sjungma@eit.uni-kl.de 19412027Sjungma@eit.uni-kl.de /** When a timing access doesn't return a success, some time later the 19512027Sjungma@eit.uni-kl.de Retry will be sent. 19612027Sjungma@eit.uni-kl.de */ 19712027Sjungma@eit.uni-kl.de Packet *sendRetry() { return peer->recvRetry(); } 19812027Sjungma@eit.uni-kl.de 19912027Sjungma@eit.uni-kl.de /** Called by the associated device if it wishes to find out the blocksize 20012027Sjungma@eit.uni-kl.de of the device on attached to the peer port. 20112027Sjungma@eit.uni-kl.de */ 20212027Sjungma@eit.uni-kl.de int peerBlockSize() { return peer->deviceBlockSize(); } 20312027Sjungma@eit.uni-kl.de 20412027Sjungma@eit.uni-kl.de /** Called by the associated device if it wishes to find out the address 20512027Sjungma@eit.uni-kl.de ranges connected to the peer ports devices. 20612027Sjungma@eit.uni-kl.de */ 20712027Sjungma@eit.uni-kl.de void getPeerAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) 20812027Sjungma@eit.uni-kl.de { peer->getDeviceAddressRanges(resp, snoop); } 20912027Sjungma@eit.uni-kl.de 21012027Sjungma@eit.uni-kl.de /** This function is a wrapper around sendFunctional() 21112027Sjungma@eit.uni-kl.de that breaks a larger, arbitrarily aligned access into 21212027Sjungma@eit.uni-kl.de appropriate chunks. The default implementation can use 21312027Sjungma@eit.uni-kl.de getBlockSize() to determine the block size and go from there. 21412027Sjungma@eit.uni-kl.de */ 21512027Sjungma@eit.uni-kl.de virtual void readBlob(Addr addr, uint8_t *p, int size); 21612027Sjungma@eit.uni-kl.de 21712027Sjungma@eit.uni-kl.de /** This function is a wrapper around sendFunctional() 21812027Sjungma@eit.uni-kl.de that breaks a larger, arbitrarily aligned access into 21912027Sjungma@eit.uni-kl.de appropriate chunks. The default implementation can use 22012027Sjungma@eit.uni-kl.de getBlockSize() to determine the block size and go from there. 22112027Sjungma@eit.uni-kl.de */ 22212027Sjungma@eit.uni-kl.de virtual void writeBlob(Addr addr, uint8_t *p, int size); 22312027Sjungma@eit.uni-kl.de 22412027Sjungma@eit.uni-kl.de /** Fill size bytes starting at addr with byte value val. This 22512027Sjungma@eit.uni-kl.de should not need to be virtual, since it can be implemented in 22612027Sjungma@eit.uni-kl.de terms of writeBlob(). However, it shouldn't be 22712027Sjungma@eit.uni-kl.de performance-critical either, so it could be if we wanted to. 22812027Sjungma@eit.uni-kl.de */ 22912027Sjungma@eit.uni-kl.de virtual void memsetBlob(Addr addr, uint8_t val, int size); 23012027Sjungma@eit.uni-kl.de 23112027Sjungma@eit.uni-kl.de private: 23212027Sjungma@eit.uni-kl.de 23312027Sjungma@eit.uni-kl.de /** Internal helper function for read/writeBlob(). 23412027Sjungma@eit.uni-kl.de */ 23512027Sjungma@eit.uni-kl.de void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd); 23612027Sjungma@eit.uni-kl.de}; 23712027Sjungma@eit.uni-kl.de 23812027Sjungma@eit.uni-kl.de/** A simple functional port that is only meant for one way communication to 23912027Sjungma@eit.uni-kl.de * physical memory. It is only meant to be used to load data into memory before 24012027Sjungma@eit.uni-kl.de * the simulation begins. 24112027Sjungma@eit.uni-kl.de */ 24212027Sjungma@eit.uni-kl.de 24312027Sjungma@eit.uni-kl.declass FunctionalPort : public Port 24412027Sjungma@eit.uni-kl.de{ 24512027Sjungma@eit.uni-kl.de public: 24612027Sjungma@eit.uni-kl.de FunctionalPort(const std::string &_name) 24712027Sjungma@eit.uni-kl.de : Port(_name) 24812027Sjungma@eit.uni-kl.de {} 24912027Sjungma@eit.uni-kl.de 25012027Sjungma@eit.uni-kl.de virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); } 25112027Sjungma@eit.uni-kl.de virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); } 25212027Sjungma@eit.uni-kl.de virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); } 25312027Sjungma@eit.uni-kl.de virtual void recvStatusChange(Status status) {} 25412027Sjungma@eit.uni-kl.de 25512027Sjungma@eit.uni-kl.de template <typename T> 25612027Sjungma@eit.uni-kl.de inline void write(Addr addr, T d) 25712027Sjungma@eit.uni-kl.de { 25812027Sjungma@eit.uni-kl.de writeBlob(addr, (uint8_t*)&d, sizeof(T)); 25912027Sjungma@eit.uni-kl.de } 26012027Sjungma@eit.uni-kl.de 26112027Sjungma@eit.uni-kl.de template <typename T> 26212027Sjungma@eit.uni-kl.de inline T read(Addr addr) 26312027Sjungma@eit.uni-kl.de { 26412027Sjungma@eit.uni-kl.de T d; 26512027Sjungma@eit.uni-kl.de readBlob(addr, (uint8_t*)&d, sizeof(T)); 26612027Sjungma@eit.uni-kl.de return d; 26712027Sjungma@eit.uni-kl.de } 26812027Sjungma@eit.uni-kl.de}; 26912027Sjungma@eit.uni-kl.de 27012027Sjungma@eit.uni-kl.de#endif //__MEM_PORT_HH__ 27112027Sjungma@eit.uni-kl.de