io_device.hh revision 8948
1545SN/A/* 28948Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited 38948Sandreas.hansson@arm.com * All rights reserved. 48948Sandreas.hansson@arm.com * 58948Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68948Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78948Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88948Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98948Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108948Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118948Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128948Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138948Sandreas.hansson@arm.com * 141762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 15545SN/A * All rights reserved. 16545SN/A * 17545SN/A * Redistribution and use in source and binary forms, with or without 18545SN/A * modification, are permitted provided that the following conditions are 19545SN/A * met: redistributions of source code must retain the above copyright 20545SN/A * notice, this list of conditions and the following disclaimer; 21545SN/A * redistributions in binary form must reproduce the above copyright 22545SN/A * notice, this list of conditions and the following disclaimer in the 23545SN/A * documentation and/or other materials provided with the distribution; 24545SN/A * neither the name of the copyright holders nor the names of its 25545SN/A * contributors may be used to endorse or promote products derived from 26545SN/A * this software without specific prior written permission. 27545SN/A * 28545SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29545SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30545SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31545SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32545SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33545SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34545SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35545SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36545SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37545SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38545SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 412665Ssaidi@eecs.umich.edu * Nathan Binkert 42545SN/A */ 43545SN/A 441310SN/A#ifndef __DEV_IO_DEVICE_HH__ 451310SN/A#define __DEV_IO_DEVICE_HH__ 46545SN/A 475386Sstever@gmail.com#include "base/fast_alloc.hh" 482542SN/A#include "mem/mem_object.hh" 493348Sbinkertn@umich.edu#include "mem/packet.hh" 503348Sbinkertn@umich.edu#include "mem/tport.hh" 514762Snate@binkert.org#include "params/BasicPioDevice.hh" 524762Snate@binkert.org#include "params/DmaDevice.hh" 534762Snate@binkert.org#include "params/PioDevice.hh" 542489SN/A#include "sim/sim_object.hh" 55545SN/A 563090Sstever@eecs.umich.educlass Event; 572384SN/Aclass PioDevice; 582489SN/Aclass DmaDevice; 592522SN/Aclass System; 60545SN/A 612489SN/A/** 622489SN/A * The PioPort class is a programmed i/o port that all devices that are 632489SN/A * sensitive to an address range use. The port takes all the memory 642489SN/A * access types and roles them into one read() and write() call that the device 658711Sandreas.hansson@arm.com * must respond to. The device must also provide getAddrRanges() function 663090Sstever@eecs.umich.edu * with which it returns the address ranges it is interested in. 673090Sstever@eecs.umich.edu */ 682914Ssaidi@eecs.umich.educlass PioPort : public SimpleTimingPort 69545SN/A{ 70545SN/A protected: 712489SN/A /** The device that this port serves. */ 722384SN/A PioDevice *device; 732384SN/A 743349Sbinkertn@umich.edu virtual Tick recvAtomic(PacketPtr pkt); 752384SN/A 768711Sandreas.hansson@arm.com virtual AddrRangeList getAddrRanges(); 772384SN/A 782384SN/A public: 793091Sstever@eecs.umich.edu 808914Sandreas.hansson@arm.com PioPort(PioDevice *dev); 812384SN/A}; 822384SN/A 832565SN/A 848922Swilliam.wang@arm.comclass DmaPort : public MasterPort 852384SN/A{ 862384SN/A protected: 875386Sstever@gmail.com struct DmaReqState : public Packet::SenderState, public FastAlloc 882784Ssaidi@eecs.umich.edu { 892784Ssaidi@eecs.umich.edu /** Event to call on the device when this transaction (all packets) 902784Ssaidi@eecs.umich.edu * complete. */ 912784Ssaidi@eecs.umich.edu Event *completionEvent; 922784Ssaidi@eecs.umich.edu 932784Ssaidi@eecs.umich.edu /** Where we came from for some sanity checking. */ 942784Ssaidi@eecs.umich.edu Port *outPort; 952784Ssaidi@eecs.umich.edu 962784Ssaidi@eecs.umich.edu /** Total number of bytes that this transaction involves. */ 972784Ssaidi@eecs.umich.edu Addr totBytes; 982784Ssaidi@eecs.umich.edu 992784Ssaidi@eecs.umich.edu /** Number of bytes that have been acked for this transaction. */ 1002784Ssaidi@eecs.umich.edu Addr numBytes; 1012784Ssaidi@eecs.umich.edu 1025534Ssaidi@eecs.umich.edu /** Amount to delay completion of dma by */ 1035534Ssaidi@eecs.umich.edu Tick delay; 1045534Ssaidi@eecs.umich.edu 1057403SAli.Saidi@ARM.com 1065534Ssaidi@eecs.umich.edu DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay) 1075534Ssaidi@eecs.umich.edu : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0), 1085534Ssaidi@eecs.umich.edu delay(_delay) 1092784Ssaidi@eecs.umich.edu {} 1102784Ssaidi@eecs.umich.edu }; 1112784Ssaidi@eecs.umich.edu 1127403SAli.Saidi@ARM.com MemObject *device; 1133349Sbinkertn@umich.edu std::list<PacketPtr> transmitList; 1142384SN/A 1152901Ssaidi@eecs.umich.edu /** The system that device/port are in. This is used to select which mode 1162565SN/A * we are currently operating in. */ 1172901Ssaidi@eecs.umich.edu System *sys; 1182565SN/A 1198832SAli.Saidi@ARM.com /** Id for all requests */ 1208832SAli.Saidi@ARM.com MasterID masterId; 1218832SAli.Saidi@ARM.com 1222565SN/A /** Number of outstanding packets the dma port has. */ 1232565SN/A int pendingCount; 1242384SN/A 1252901Ssaidi@eecs.umich.edu /** If a dmaAction is in progress. */ 1262901Ssaidi@eecs.umich.edu int actionInProgress; 1272901Ssaidi@eecs.umich.edu 1282901Ssaidi@eecs.umich.edu /** If we need to drain, keep the drain event around until we're done 1292901Ssaidi@eecs.umich.edu * here.*/ 1302901Ssaidi@eecs.umich.edu Event *drainEvent; 1312901Ssaidi@eecs.umich.edu 1324435Ssaidi@eecs.umich.edu /** time to wait between sending another packet, increases as NACKs are 1334435Ssaidi@eecs.umich.edu * recived, decreases as responses are recived. */ 1344435Ssaidi@eecs.umich.edu Tick backoffTime; 1354435Ssaidi@eecs.umich.edu 1367403SAli.Saidi@ARM.com /** Minimum time that device should back off for after failed sendTiming */ 1377403SAli.Saidi@ARM.com Tick minBackoffDelay; 1387403SAli.Saidi@ARM.com 1397403SAli.Saidi@ARM.com /** Maximum time that device should back off for after failed sendTiming */ 1407403SAli.Saidi@ARM.com Tick maxBackoffDelay; 1417403SAli.Saidi@ARM.com 1424435Ssaidi@eecs.umich.edu /** If the port is currently waiting for a retry before it can send whatever 1434435Ssaidi@eecs.umich.edu * it is that it's sending. */ 1444435Ssaidi@eecs.umich.edu bool inRetry; 1454435Ssaidi@eecs.umich.edu 1468630SMitchell.Hayenga@ARM.com /** Port accesses a cache which requires snooping */ 1478630SMitchell.Hayenga@ARM.com bool recvSnoops; 1488630SMitchell.Hayenga@ARM.com 1493349Sbinkertn@umich.edu virtual bool recvTiming(PacketPtr pkt); 1508948Sandreas.hansson@arm.com 1518948Sandreas.hansson@arm.com virtual bool recvTimingSnoop(PacketPtr pkt) 1528630SMitchell.Hayenga@ARM.com { 1538948Sandreas.hansson@arm.com if (!recvSnoops) 1548948Sandreas.hansson@arm.com panic("%s was not expecting a snoop\n", name()); 1558948Sandreas.hansson@arm.com return true; 1568948Sandreas.hansson@arm.com } 1578630SMitchell.Hayenga@ARM.com 1588948Sandreas.hansson@arm.com virtual Tick recvAtomicSnoop(PacketPtr pkt) 1598948Sandreas.hansson@arm.com { 1608948Sandreas.hansson@arm.com if (!recvSnoops) 1618948Sandreas.hansson@arm.com panic("%s was not expecting a snoop\n", name()); 1628948Sandreas.hansson@arm.com return 0; 1638630SMitchell.Hayenga@ARM.com } 1648948Sandreas.hansson@arm.com 1658948Sandreas.hansson@arm.com virtual void recvFunctionalSnoop(PacketPtr pkt) 1668630SMitchell.Hayenga@ARM.com { 1678948Sandreas.hansson@arm.com if (!recvSnoops) 1688948Sandreas.hansson@arm.com panic("%s was not expecting a snoop\n", name()); 1698630SMitchell.Hayenga@ARM.com } 1702384SN/A 1712657Ssaidi@eecs.umich.edu virtual void recvRetry() ; 1722384SN/A 1738922Swilliam.wang@arm.com virtual bool isSnooping() const { return recvSnoops; } 1742384SN/A 1754435Ssaidi@eecs.umich.edu void queueDma(PacketPtr pkt, bool front = false); 1764435Ssaidi@eecs.umich.edu void sendDma(); 1774435Ssaidi@eecs.umich.edu 1784435Ssaidi@eecs.umich.edu /** event to give us a kick every time we backoff time is reached. */ 1794435Ssaidi@eecs.umich.edu EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent; 1802489SN/A 1812384SN/A public: 1828630SMitchell.Hayenga@ARM.com DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff, 1838630SMitchell.Hayenga@ARM.com bool recv_snoops = false); 1842565SN/A 1852641Sstever@eecs.umich.edu void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 1867607SGene.Wu@arm.com uint8_t *data, Tick delay, Request::Flags flag = 0); 1872565SN/A 1882565SN/A bool dmaPending() { return pendingCount > 0; } 1892384SN/A 1906227Snate@binkert.org unsigned cacheBlockSize() const { return peerBlockSize(); } 1912901Ssaidi@eecs.umich.edu unsigned int drain(Event *de); 1922384SN/A}; 1932384SN/A 1942489SN/A/** 1952489SN/A * This device is the base class which all devices senstive to an address range 1962489SN/A * inherit from. There are three pure virtual functions which all devices must 1978711Sandreas.hansson@arm.com * implement getAddrRanges(), read(), and write(). The magic do choose which 1982489SN/A * mode we are in, etc is handled by the PioPort so the device doesn't have to 1992489SN/A * bother. 2002489SN/A */ 2012542SN/Aclass PioDevice : public MemObject 2022384SN/A{ 2032384SN/A protected: 2042901Ssaidi@eecs.umich.edu System *sys; 2052901Ssaidi@eecs.umich.edu 2062489SN/A /** The pioPort that handles the requests for us and provides us requests 2072489SN/A * that it sees. */ 2088851Sandreas.hansson@arm.com PioPort pioPort; 2092384SN/A 2108711Sandreas.hansson@arm.com /** 2118711Sandreas.hansson@arm.com * Every PIO device is obliged to provide an implementation that 2128711Sandreas.hansson@arm.com * returns the address ranges the device responds to. 2138711Sandreas.hansson@arm.com * 2148711Sandreas.hansson@arm.com * @return a list of non-overlapping address ranges 2158711Sandreas.hansson@arm.com */ 2168711Sandreas.hansson@arm.com virtual AddrRangeList getAddrRanges() = 0; 2172384SN/A 2183090Sstever@eecs.umich.edu /** Pure virtual function that the device must implement. Called 2193090Sstever@eecs.umich.edu * when a read command is recieved by the port. 2202523SN/A * @param pkt Packet describing this request 2212523SN/A * @return number of ticks it took to complete 2222523SN/A */ 2233349Sbinkertn@umich.edu virtual Tick read(PacketPtr pkt) = 0; 2242384SN/A 2252489SN/A /** Pure virtual function that the device must implement. Called when a 2262523SN/A * write command is recieved by the port. 2272523SN/A * @param pkt Packet describing this request 2282523SN/A * @return number of ticks it took to complete 2292523SN/A */ 2303349Sbinkertn@umich.edu virtual Tick write(PacketPtr pkt) = 0; 231545SN/A 232545SN/A public: 2334762Snate@binkert.org typedef PioDeviceParams Params; 2344762Snate@binkert.org PioDevice(const Params *p); 2354762Snate@binkert.org virtual ~PioDevice(); 2364762Snate@binkert.org 2374762Snate@binkert.org const Params * 2384762Snate@binkert.org params() const 2392512SN/A { 2404762Snate@binkert.org return dynamic_cast<const Params *>(_params); 2414762Snate@binkert.org } 2422384SN/A 2432541SN/A virtual void init(); 2442541SN/A 2452901Ssaidi@eecs.umich.edu virtual unsigned int drain(Event *de); 2462901Ssaidi@eecs.umich.edu 2478922Swilliam.wang@arm.com virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1); 2488598Ssteve.reinhardt@amd.com 2492489SN/A friend class PioPort; 2502489SN/A 251545SN/A}; 252545SN/A 2532512SN/Aclass BasicPioDevice : public PioDevice 2542512SN/A{ 2552512SN/A protected: 2562512SN/A /** Address that the device listens to. */ 2572512SN/A Addr pioAddr; 2582512SN/A 2592512SN/A /** Size that the device's address range. */ 2602521SN/A Addr pioSize; 2612512SN/A 2622512SN/A /** Delay that the device experinces on an access. */ 2632512SN/A Tick pioDelay; 2642512SN/A 2652512SN/A public: 2664762Snate@binkert.org typedef BasicPioDeviceParams Params; 2674762Snate@binkert.org BasicPioDevice(const Params *p); 2684762Snate@binkert.org 2694762Snate@binkert.org const Params * 2704762Snate@binkert.org params() const 2714762Snate@binkert.org { 2724762Snate@binkert.org return dynamic_cast<const Params *>(_params); 2734762Snate@binkert.org } 2742512SN/A 2758711Sandreas.hansson@arm.com /** 2768711Sandreas.hansson@arm.com * Determine the address ranges that this device responds to. 2778711Sandreas.hansson@arm.com * 2788711Sandreas.hansson@arm.com * @return a list of non-overlapping address ranges 2792539SN/A */ 2808711Sandreas.hansson@arm.com virtual AddrRangeList getAddrRanges(); 2812539SN/A 2822512SN/A}; 2832512SN/A 284545SN/Aclass DmaDevice : public PioDevice 285545SN/A{ 2864435Ssaidi@eecs.umich.edu protected: 2878851Sandreas.hansson@arm.com DmaPort dmaPort; 288545SN/A 289545SN/A public: 2904762Snate@binkert.org typedef DmaDeviceParams Params; 2914762Snate@binkert.org DmaDevice(const Params *p); 292545SN/A virtual ~DmaDevice(); 2932384SN/A 2944762Snate@binkert.org const Params * 2954762Snate@binkert.org params() const 2964762Snate@binkert.org { 2974762Snate@binkert.org return dynamic_cast<const Params *>(_params); 2984762Snate@binkert.org } 2994762Snate@binkert.org 3008851Sandreas.hansson@arm.com void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, 3018851Sandreas.hansson@arm.com Tick delay = 0) 3024022Sstever@eecs.umich.edu { 3038851Sandreas.hansson@arm.com dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); 3044022Sstever@eecs.umich.edu } 3052565SN/A 3068851Sandreas.hansson@arm.com void dmaRead(Addr addr, int size, Event *event, uint8_t *data, 3078851Sandreas.hansson@arm.com Tick delay = 0) 3084263Ssaidi@eecs.umich.edu { 3098851Sandreas.hansson@arm.com dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); 3104263Ssaidi@eecs.umich.edu } 3112565SN/A 3128851Sandreas.hansson@arm.com bool dmaPending() { return dmaPort.dmaPending(); } 3138851Sandreas.hansson@arm.com 3148851Sandreas.hansson@arm.com virtual void init(); 3152565SN/A 3162901Ssaidi@eecs.umich.edu virtual unsigned int drain(Event *de); 3172901Ssaidi@eecs.umich.edu 3188851Sandreas.hansson@arm.com unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); } 3194263Ssaidi@eecs.umich.edu 3208922Swilliam.wang@arm.com virtual MasterPort &getMasterPort(const std::string &if_name, 3218922Swilliam.wang@arm.com int idx = -1); 3222489SN/A 3232489SN/A friend class DmaPort; 324545SN/A}; 325545SN/A 3262384SN/A 3271310SN/A#endif // __DEV_IO_DEVICE_HH__ 328