dma_device.hh revision 8832
12735Sktlim@umich.edu/* 210319SAndreas.Sandberg@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 310319SAndreas.Sandberg@ARM.com * All rights reserved. 410319SAndreas.Sandberg@ARM.com * 510319SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 610319SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 710319SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 810319SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 910319SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 1010319SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 1110319SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 1210319SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 1310319SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 142735Sktlim@umich.edu * this software without specific prior written permission. 1511303Ssteve.reinhardt@amd.com * 162735Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172735Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182735Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192735Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202735Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212735Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222735Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232735Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242735Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252735Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262735Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272735Sktlim@umich.edu * 282735Sktlim@umich.edu * Authors: Ali Saidi 292735Sktlim@umich.edu * Nathan Binkert 302735Sktlim@umich.edu */ 312735Sktlim@umich.edu 322735Sktlim@umich.edu#ifndef __DEV_IO_DEVICE_HH__ 332735Sktlim@umich.edu#define __DEV_IO_DEVICE_HH__ 342735Sktlim@umich.edu 352735Sktlim@umich.edu#include "base/fast_alloc.hh" 362735Sktlim@umich.edu#include "mem/mem_object.hh" 372735Sktlim@umich.edu#include "mem/packet.hh" 382735Sktlim@umich.edu#include "mem/tport.hh" 392735Sktlim@umich.edu#include "params/BasicPioDevice.hh" 402735Sktlim@umich.edu#include "params/DmaDevice.hh" 412735Sktlim@umich.edu#include "params/PioDevice.hh" 4210319SAndreas.Sandberg@ARM.com#include "sim/sim_object.hh" 432735Sktlim@umich.edu 442735Sktlim@umich.educlass Event; 4510319SAndreas.Sandberg@ARM.comclass PioDevice; 4610319SAndreas.Sandberg@ARM.comclass DmaDevice; 4710319SAndreas.Sandberg@ARM.comclass System; 4810319SAndreas.Sandberg@ARM.com 4910319SAndreas.Sandberg@ARM.com/** 5010319SAndreas.Sandberg@ARM.com * The PioPort class is a programmed i/o port that all devices that are 5110529Smorr@cs.wisc.edu * sensitive to an address range use. The port takes all the memory 5212104Snathanael.premillieu@arm.com * access types and roles them into one read() and write() call that the device 5310319SAndreas.Sandberg@ARM.com * must respond to. The device must also provide getAddrRanges() function 5410319SAndreas.Sandberg@ARM.com * with which it returns the address ranges it is interested in. 5511608Snikos.nikoleris@arm.com */ 562735Sktlim@umich.educlass PioPort : public SimpleTimingPort 572735Sktlim@umich.edu{ 5810319SAndreas.Sandberg@ARM.com protected: 5910319SAndreas.Sandberg@ARM.com /** The device that this port serves. */ 6010319SAndreas.Sandberg@ARM.com PioDevice *device; 6110319SAndreas.Sandberg@ARM.com 6210319SAndreas.Sandberg@ARM.com virtual Tick recvAtomic(PacketPtr pkt); 6310319SAndreas.Sandberg@ARM.com 6410319SAndreas.Sandberg@ARM.com virtual AddrRangeList getAddrRanges(); 6510319SAndreas.Sandberg@ARM.com 6610319SAndreas.Sandberg@ARM.com public: 6710319SAndreas.Sandberg@ARM.com 6810319SAndreas.Sandberg@ARM.com PioPort(PioDevice *dev, System *s, std::string pname = "-pioport"); 6910319SAndreas.Sandberg@ARM.com}; 7010319SAndreas.Sandberg@ARM.com 7110319SAndreas.Sandberg@ARM.com 722735Sktlim@umich.educlass DmaPort : public Port 732735Sktlim@umich.edu{ 7410319SAndreas.Sandberg@ARM.com protected: 7510319SAndreas.Sandberg@ARM.com struct DmaReqState : public Packet::SenderState, public FastAlloc 7610319SAndreas.Sandberg@ARM.com { 7710319SAndreas.Sandberg@ARM.com /** Event to call on the device when this transaction (all packets) 7810319SAndreas.Sandberg@ARM.com * complete. */ 7910319SAndreas.Sandberg@ARM.com Event *completionEvent; 8010319SAndreas.Sandberg@ARM.com 8110319SAndreas.Sandberg@ARM.com /** Where we came from for some sanity checking. */ 8210319SAndreas.Sandberg@ARM.com Port *outPort; 8310319SAndreas.Sandberg@ARM.com 8410319SAndreas.Sandberg@ARM.com /** Total number of bytes that this transaction involves. */ 8510319SAndreas.Sandberg@ARM.com Addr totBytes; 8610319SAndreas.Sandberg@ARM.com 8710319SAndreas.Sandberg@ARM.com /** Number of bytes that have been acked for this transaction. */ 8810319SAndreas.Sandberg@ARM.com Addr numBytes; 892735Sktlim@umich.edu 902735Sktlim@umich.edu /** Amount to delay completion of dma by */ 9110319SAndreas.Sandberg@ARM.com Tick delay; 9210319SAndreas.Sandberg@ARM.com 9310319SAndreas.Sandberg@ARM.com 9410319SAndreas.Sandberg@ARM.com DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay) 9510319SAndreas.Sandberg@ARM.com : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0), 9610319SAndreas.Sandberg@ARM.com delay(_delay) 9710319SAndreas.Sandberg@ARM.com {} 9810319SAndreas.Sandberg@ARM.com }; 9910319SAndreas.Sandberg@ARM.com 10010319SAndreas.Sandberg@ARM.com MemObject *device; 10110319SAndreas.Sandberg@ARM.com std::list<PacketPtr> transmitList; 10210319SAndreas.Sandberg@ARM.com 10310319SAndreas.Sandberg@ARM.com /** The system that device/port are in. This is used to select which mode 1042735Sktlim@umich.edu * we are currently operating in. */ 1052735Sktlim@umich.edu System *sys; 10610319SAndreas.Sandberg@ARM.com 1072735Sktlim@umich.edu /** Id for all requests */ 1082735Sktlim@umich.edu MasterID masterId; 1092735Sktlim@umich.edu 11010319SAndreas.Sandberg@ARM.com /** Number of outstanding packets the dma port has. */ 11110319SAndreas.Sandberg@ARM.com int pendingCount; 1122735Sktlim@umich.edu 1132735Sktlim@umich.edu /** If a dmaAction is in progress. */ 11410319SAndreas.Sandberg@ARM.com int actionInProgress; 11510319SAndreas.Sandberg@ARM.com 1162735Sktlim@umich.edu /** If we need to drain, keep the drain event around until we're done 1172735Sktlim@umich.edu * here.*/ 1182735Sktlim@umich.edu Event *drainEvent; 11910319SAndreas.Sandberg@ARM.com 12010319SAndreas.Sandberg@ARM.com /** time to wait between sending another packet, increases as NACKs are 1212735Sktlim@umich.edu * recived, decreases as responses are recived. */ 12210319SAndreas.Sandberg@ARM.com Tick backoffTime; 1232735Sktlim@umich.edu 12410319SAndreas.Sandberg@ARM.com /** Minimum time that device should back off for after failed sendTiming */ 12510319SAndreas.Sandberg@ARM.com Tick minBackoffDelay; 12610319SAndreas.Sandberg@ARM.com 12710319SAndreas.Sandberg@ARM.com /** Maximum time that device should back off for after failed sendTiming */ 12810319SAndreas.Sandberg@ARM.com Tick maxBackoffDelay; 12910319SAndreas.Sandberg@ARM.com 13010319SAndreas.Sandberg@ARM.com /** If the port is currently waiting for a retry before it can send whatever 1312735Sktlim@umich.edu * it is that it's sending. */ 13210319SAndreas.Sandberg@ARM.com bool inRetry; 13310319SAndreas.Sandberg@ARM.com 13410319SAndreas.Sandberg@ARM.com /** Port accesses a cache which requires snooping */ 13510319SAndreas.Sandberg@ARM.com bool recvSnoops; 13610319SAndreas.Sandberg@ARM.com 13710319SAndreas.Sandberg@ARM.com virtual bool recvTiming(PacketPtr pkt); 13810319SAndreas.Sandberg@ARM.com virtual Tick recvAtomic(PacketPtr pkt) 1392735Sktlim@umich.edu { 14010319SAndreas.Sandberg@ARM.com if (recvSnoops) return 0; 14110319SAndreas.Sandberg@ARM.com 14210319SAndreas.Sandberg@ARM.com panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN 14310319SAndreas.Sandberg@ARM.com } 14410319SAndreas.Sandberg@ARM.com virtual void recvFunctional(PacketPtr pkt) 1452735Sktlim@umich.edu { 14610319SAndreas.Sandberg@ARM.com if (recvSnoops) return; 14710319SAndreas.Sandberg@ARM.com 14810319SAndreas.Sandberg@ARM.com panic("dma port shouldn't be used for pio access."); 14910319SAndreas.Sandberg@ARM.com } 15010319SAndreas.Sandberg@ARM.com 1512735Sktlim@umich.edu virtual void recvRangeChange() 15210319SAndreas.Sandberg@ARM.com { 1532735Sktlim@umich.edu // DMA port is a master with a single slave so there is no choice and 15410319SAndreas.Sandberg@ARM.com // thus no need to worry about any address changes 15510319SAndreas.Sandberg@ARM.com } 15610319SAndreas.Sandberg@ARM.com 15710319SAndreas.Sandberg@ARM.com virtual void recvRetry() ; 15810319SAndreas.Sandberg@ARM.com 15910319SAndreas.Sandberg@ARM.com virtual bool isSnooping() 16010319SAndreas.Sandberg@ARM.com { return recvSnoops; } 16110319SAndreas.Sandberg@ARM.com 16210319SAndreas.Sandberg@ARM.com void queueDma(PacketPtr pkt, bool front = false); 16310319SAndreas.Sandberg@ARM.com void sendDma(); 16410319SAndreas.Sandberg@ARM.com 16510319SAndreas.Sandberg@ARM.com /** event to give us a kick every time we backoff time is reached. */ 16610319SAndreas.Sandberg@ARM.com EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent; 16710319SAndreas.Sandberg@ARM.com 16810319SAndreas.Sandberg@ARM.com public: 16910319SAndreas.Sandberg@ARM.com DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff, 17010319SAndreas.Sandberg@ARM.com bool recv_snoops = false); 17110319SAndreas.Sandberg@ARM.com 17210319SAndreas.Sandberg@ARM.com void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 17310319SAndreas.Sandberg@ARM.com uint8_t *data, Tick delay, Request::Flags flag = 0); 17410319SAndreas.Sandberg@ARM.com 17510319SAndreas.Sandberg@ARM.com bool dmaPending() { return pendingCount > 0; } 17610319SAndreas.Sandberg@ARM.com 17710319SAndreas.Sandberg@ARM.com unsigned cacheBlockSize() const { return peerBlockSize(); } 17810319SAndreas.Sandberg@ARM.com unsigned int drain(Event *de); 17911303Ssteve.reinhardt@amd.com}; 18011303Ssteve.reinhardt@amd.com 18111303Ssteve.reinhardt@amd.com/** 18211303Ssteve.reinhardt@amd.com * This device is the base class which all devices senstive to an address range 18311303Ssteve.reinhardt@amd.com * inherit from. There are three pure virtual functions which all devices must 18411303Ssteve.reinhardt@amd.com * implement getAddrRanges(), read(), and write(). The magic do choose which 18511303Ssteve.reinhardt@amd.com * mode we are in, etc is handled by the PioPort so the device doesn't have to 18610319SAndreas.Sandberg@ARM.com * bother. 18711608Snikos.nikoleris@arm.com */ 18811303Ssteve.reinhardt@amd.comclass PioDevice : public MemObject 18911303Ssteve.reinhardt@amd.com{ 19011303Ssteve.reinhardt@amd.com protected: 19110319SAndreas.Sandberg@ARM.com System *sys; 19211303Ssteve.reinhardt@amd.com 19311303Ssteve.reinhardt@amd.com /** The pioPort that handles the requests for us and provides us requests 19411303Ssteve.reinhardt@amd.com * that it sees. */ 19511303Ssteve.reinhardt@amd.com PioPort *pioPort; 19611303Ssteve.reinhardt@amd.com 19711303Ssteve.reinhardt@amd.com /** 19811303Ssteve.reinhardt@amd.com * Every PIO device is obliged to provide an implementation that 19911303Ssteve.reinhardt@amd.com * returns the address ranges the device responds to. 20011608Snikos.nikoleris@arm.com * 20111303Ssteve.reinhardt@amd.com * @return a list of non-overlapping address ranges 20211303Ssteve.reinhardt@amd.com */ 20311303Ssteve.reinhardt@amd.com virtual AddrRangeList getAddrRanges() = 0; 20411303Ssteve.reinhardt@amd.com 20511303Ssteve.reinhardt@amd.com /** Pure virtual function that the device must implement. Called 20611303Ssteve.reinhardt@amd.com * when a read command is recieved by the port. 20711303Ssteve.reinhardt@amd.com * @param pkt Packet describing this request 20811303Ssteve.reinhardt@amd.com * @return number of ticks it took to complete 20910319SAndreas.Sandberg@ARM.com */ 21011608Snikos.nikoleris@arm.com virtual Tick read(PacketPtr pkt) = 0; 21110319SAndreas.Sandberg@ARM.com 21210319SAndreas.Sandberg@ARM.com /** Pure virtual function that the device must implement. Called when a 21310319SAndreas.Sandberg@ARM.com * write command is recieved by the port. 21410319SAndreas.Sandberg@ARM.com * @param pkt Packet describing this request 21510319SAndreas.Sandberg@ARM.com * @return number of ticks it took to complete 21610319SAndreas.Sandberg@ARM.com */ 21710319SAndreas.Sandberg@ARM.com virtual Tick write(PacketPtr pkt) = 0; 21810319SAndreas.Sandberg@ARM.com 21910319SAndreas.Sandberg@ARM.com public: 22010319SAndreas.Sandberg@ARM.com typedef PioDeviceParams Params; 22110319SAndreas.Sandberg@ARM.com PioDevice(const Params *p); 22210319SAndreas.Sandberg@ARM.com virtual ~PioDevice(); 22310319SAndreas.Sandberg@ARM.com 22410319SAndreas.Sandberg@ARM.com const Params * 22510319SAndreas.Sandberg@ARM.com params() const 22610319SAndreas.Sandberg@ARM.com { 22710319SAndreas.Sandberg@ARM.com return dynamic_cast<const Params *>(_params); 22810319SAndreas.Sandberg@ARM.com } 22910319SAndreas.Sandberg@ARM.com 23010319SAndreas.Sandberg@ARM.com virtual void init(); 23110319SAndreas.Sandberg@ARM.com 23211877Sbrandon.potter@amd.com virtual unsigned int drain(Event *de); 23310319SAndreas.Sandberg@ARM.com 23410319SAndreas.Sandberg@ARM.com virtual Port *getPort(const std::string &if_name, int idx = -1); 2352735Sktlim@umich.edu 2362735Sktlim@umich.edu friend class PioPort; 23710319SAndreas.Sandberg@ARM.com 2382735Sktlim@umich.edu}; 23910319SAndreas.Sandberg@ARM.com 24010319SAndreas.Sandberg@ARM.comclass BasicPioDevice : public PioDevice 24110319SAndreas.Sandberg@ARM.com{ 24210319SAndreas.Sandberg@ARM.com protected: 2437520Sgblack@eecs.umich.edu /** Address that the device listens to. */ 24410319SAndreas.Sandberg@ARM.com Addr pioAddr; 24510319SAndreas.Sandberg@ARM.com 24610319SAndreas.Sandberg@ARM.com /** Size that the device's address range. */ 24710319SAndreas.Sandberg@ARM.com Addr pioSize; 24810319SAndreas.Sandberg@ARM.com 2495702Ssaidi@eecs.umich.edu /** Delay that the device experinces on an access. */ 2505702Ssaidi@eecs.umich.edu Tick pioDelay; 2515702Ssaidi@eecs.umich.edu 2525702Ssaidi@eecs.umich.edu public: 2535702Ssaidi@eecs.umich.edu typedef BasicPioDeviceParams Params; 25410319SAndreas.Sandberg@ARM.com BasicPioDevice(const Params *p); 2558779Sgblack@eecs.umich.edu 25610319SAndreas.Sandberg@ARM.com const Params * 2576973Stjones1@inf.ed.ac.uk params() const 25810319SAndreas.Sandberg@ARM.com { 25910319SAndreas.Sandberg@ARM.com return dynamic_cast<const Params *>(_params); 26010319SAndreas.Sandberg@ARM.com } 26110319SAndreas.Sandberg@ARM.com 26210319SAndreas.Sandberg@ARM.com /** 26310319SAndreas.Sandberg@ARM.com * Determine the address ranges that this device responds to. 26410319SAndreas.Sandberg@ARM.com * 26510319SAndreas.Sandberg@ARM.com * @return a list of non-overlapping address ranges 26610319SAndreas.Sandberg@ARM.com */ 26710319SAndreas.Sandberg@ARM.com virtual AddrRangeList getAddrRanges(); 26810319SAndreas.Sandberg@ARM.com 26910319SAndreas.Sandberg@ARM.com}; 27010319SAndreas.Sandberg@ARM.com 27110319SAndreas.Sandberg@ARM.comclass DmaDevice : public PioDevice 27210319SAndreas.Sandberg@ARM.com{ 27310319SAndreas.Sandberg@ARM.com protected: 27410319SAndreas.Sandberg@ARM.com DmaPort *dmaPort; 27510319SAndreas.Sandberg@ARM.com 27610319SAndreas.Sandberg@ARM.com public: 27710529Smorr@cs.wisc.edu typedef DmaDeviceParams Params; 27810529Smorr@cs.wisc.edu DmaDevice(const Params *p); 27910529Smorr@cs.wisc.edu virtual ~DmaDevice(); 28010529Smorr@cs.wisc.edu 28110319SAndreas.Sandberg@ARM.com const Params * 28210319SAndreas.Sandberg@ARM.com params() const 28310319SAndreas.Sandberg@ARM.com { 28410319SAndreas.Sandberg@ARM.com return dynamic_cast<const Params *>(_params); 28510319SAndreas.Sandberg@ARM.com } 28610319SAndreas.Sandberg@ARM.com 28710319SAndreas.Sandberg@ARM.com void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) 28810319SAndreas.Sandberg@ARM.com { 28910319SAndreas.Sandberg@ARM.com dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); 29012106SRekai.GonzalezAlberquilla@arm.com } 29110319SAndreas.Sandberg@ARM.com 29212106SRekai.GonzalezAlberquilla@arm.com void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) 29310319SAndreas.Sandberg@ARM.com { 29410319SAndreas.Sandberg@ARM.com dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); 29510319SAndreas.Sandberg@ARM.com } 29610319SAndreas.Sandberg@ARM.com 2972735Sktlim@umich.edu bool dmaPending() { return dmaPort->dmaPending(); } 29810319SAndreas.Sandberg@ARM.com 29910319SAndreas.Sandberg@ARM.com virtual unsigned int drain(Event *de); 300 301 unsigned cacheBlockSize() const { return dmaPort->cacheBlockSize(); } 302 303 virtual Port *getPort(const std::string &if_name, int idx = -1); 304 305 friend class DmaPort; 306}; 307 308 309#endif // __DEV_IO_DEVICE_HH__ 310