X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fio_device.hh;h=804133893275e694d81c5c5186c6501546efc158;hb=d040db5361603104bfa7a9f74cd571d21be87f89;hp=cd7a5296ac078b21c8a10bb481cfad178ff1887d;hpb=12b7ebcbcab1c5ea30065ea45908e5711b05b63f;p=gem5.git diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index cd7a5296a..804133893 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -32,132 +44,77 @@ #ifndef __DEV_IO_DEVICE_HH__ #define __DEV_IO_DEVICE_HH__ -#include "mem/mem_object.hh" -#include "mem/packet.hh" #include "mem/tport.hh" -#include "sim/sim_object.hh" +#include "params/BasicPioDevice.hh" +#include "params/PioDevice.hh" +#include "sim/clocked_object.hh" -class Event; -class Platform; class PioDevice; -class DmaDevice; class System; /** * The PioPort class is a programmed i/o port that all devices that are * sensitive to an address range use. The port takes all the memory * access types and roles them into one read() and write() call that the device - * must respond to. The device must also provide the addressRanges() function + * must respond to. The device must also provide getAddrRanges() function * with which it returns the address ranges it is interested in. */ +template class PioPort : public SimpleTimingPort { protected: /** The device that this port serves. */ - PioDevice *device; - - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop); - - public: - - PioPort(PioDevice *dev, System *s, std::string pname = "-pioport"); -}; + Device *device; - -class DmaPort : public Port -{ - protected: - struct DmaReqState : public Packet::SenderState + Tick + recvAtomic(PacketPtr pkt) override { - /** Event to call on the device when this transaction (all packets) - * complete. */ - Event *completionEvent; - - /** Where we came from for some sanity checking. */ - Port *outPort; - - /** Total number of bytes that this transaction involves. */ - Addr totBytes; - - /** Number of bytes that have been acked for this transaction. */ - Addr numBytes; - - DmaReqState(Event *ce, Port *p, Addr tb) - : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0) - {} - }; - - DmaDevice *device; - std::list transmitList; - - /** The system that device/port are in. This is used to select which mode - * we are currently operating in. */ - System *sys; - - /** Number of outstanding packets the dma port has. */ - int pendingCount; - - /** If a dmaAction is in progress. */ - int actionInProgress; - - /** If we need to drain, keep the drain event around until we're done - * here.*/ - Event *drainEvent; - - virtual bool recvTiming(PacketPtr pkt); - virtual Tick recvAtomic(PacketPtr pkt) - { panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN } - virtual void recvFunctional(PacketPtr pkt) - { panic("dma port shouldn't be used for pio access."); } - - virtual void recvStatusChange(Status status) - { ; } - - virtual void recvRetry() ; - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + // Technically the packet only reaches us after the header delay, + // and typically we also need to deserialise any payload. + Tick receive_delay = pkt->headerDelay + pkt->payloadDelay; + pkt->headerDelay = pkt->payloadDelay = 0; + + const Tick delay = + pkt->isRead() ? device->read(pkt) : device->write(pkt); + assert(pkt->isResponse() || pkt->isError()); + return delay + receive_delay; + } - void sendDma(PacketPtr pkt, bool front = false); + AddrRangeList + getAddrRanges() const override + { + return device->getAddrRanges(); + } public: - DmaPort(DmaDevice *dev, System *s); - - void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, - uint8_t *data = NULL); - - bool dmaPending() { return pendingCount > 0; } - - int cacheBlockSize() { return peerBlockSize(); } - unsigned int drain(Event *de); + PioPort(Device *dev) : + SimpleTimingPort(dev->name() + ".pio", dev), device(dev) + {} }; /** * This device is the base class which all devices senstive to an address range * inherit from. There are three pure virtual functions which all devices must - * implement addressRanges(), read(), and write(). The magic do choose which + * implement getAddrRanges(), read(), and write(). The magic do choose which * mode we are in, etc is handled by the PioPort so the device doesn't have to * bother. */ -class PioDevice : public MemObject +class PioDevice : public ClockedObject { protected: - - /** The platform we are in. This is used to decide what type of memory - * transaction we should perform. */ - Platform *platform; - System *sys; /** The pioPort that handles the requests for us and provides us requests * that it sees. */ - PioPort *pioPort; + PioPort pioPort; - virtual void addressRanges(AddrRangeList &range_list) = 0; + /** + * Every PIO device is obliged to provide an implementation that + * returns the address ranges the device responds to. + * + * @return a list of non-overlapping address ranges + */ + virtual AddrRangeList getAddrRanges() const = 0; /** Pure virtual function that the device must implement. Called * when a read command is recieved by the port. @@ -174,56 +131,27 @@ class PioDevice : public MemObject virtual Tick write(PacketPtr pkt) = 0; public: - /** Params struct which is extended through each device based on - * the parameters it needs. Since we are re-writing everything, we - * might as well start from the bottom this time. */ - struct Params - { - std::string name; - Platform *platform; - System *system; - }; - - protected: - Params *_params; - - public: - const Params *params() const { return _params; } - - PioDevice(Params *p) - : MemObject(p->name), platform(p->platform), sys(p->system), - pioPort(NULL), _params(p) - {} - + typedef PioDeviceParams Params; + PioDevice(const Params *p); virtual ~PioDevice(); - virtual void init(); - - virtual unsigned int drain(Event *de); - - virtual Port *getPort(const std::string &if_name, int idx = -1) + const Params * + params() const { - if (if_name == "pio") { - if (pioPort != NULL) - panic("pio port already connected to."); - pioPort = new PioPort(this, sys); - return pioPort; - } else - return NULL; + return dynamic_cast(_params); } - friend class PioPort; + + void init() override; + + Port &getPort(const std::string &if_name, + PortID idx=InvalidPortID) override; + + friend class PioPort; }; class BasicPioDevice : public PioDevice { - public: - struct Params : public PioDevice::Params - { - Addr pio_addr; - Tick pio_delay; - }; - protected: /** Address that the device listens to. */ Addr pioAddr; @@ -235,62 +163,21 @@ class BasicPioDevice : public PioDevice Tick pioDelay; public: - BasicPioDevice(Params *p) - : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), - pioDelay(p->pio_delay) - {} - - /** return the address ranges that this device responds to. - * @param range_list range list to populate with ranges - */ - void addressRanges(AddrRangeList &range_list); - -}; - -class DmaDevice : public PioDevice -{ - protected: - DmaPort *dmaPort; - - public: - DmaDevice(Params *p); - virtual ~DmaDevice(); - - void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) - { - dmaPort->dmaAction(MemCmd::WriteInvalidateReq, - addr, size, event, data); - } + typedef BasicPioDeviceParams Params; + BasicPioDevice(const Params *p, Addr size); - void dmaRead(Addr addr, int size, Event *event, uint8_t *data) + const Params * + params() const { - dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data); + return dynamic_cast(_params); } - bool dmaPending() { return dmaPort->dmaPending(); } - - virtual unsigned int drain(Event *de); - - int cacheBlockSize() { return dmaPort->cacheBlockSize(); } - - virtual Port *getPort(const std::string &if_name, int idx = -1) - { - if (if_name == "pio") { - if (pioPort != NULL) - panic("pio port already connected to."); - pioPort = new PioPort(this, sys); - return pioPort; - } else if (if_name == "dma") { - if (dmaPort != NULL) - panic("dma port already connected to."); - dmaPort = new DmaPort(this, sys); - return dmaPort; - } else - return NULL; - } - - friend class DmaPort; + /** + * Determine the address ranges that this device responds to. + * + * @return a list of non-overlapping address ranges + */ + AddrRangeList getAddrRanges() const override; }; - #endif // __DEV_IO_DEVICE_HH__