X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fio_device.hh;h=36787c13efd84f4be44694af2c155d465ba6b81b;hb=9957035a42653a0666e30c744ab02fb0074db3a3;hp=cd7a5296ac078b21c8a10bb481cfad178ff1887d;hpb=30f101881faad95e4a51fcb7bd7f564d660faae4;p=gem5.git diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index cd7a5296a..36787c13e 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -32,9 +32,13 @@ #ifndef __DEV_IO_DEVICE_HH__ #define __DEV_IO_DEVICE_HH__ +#include "base/fast_alloc.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/tport.hh" +#include "params/BasicPioDevice.hh" +#include "params/DmaDevice.hh" +#include "params/PioDevice.hh" #include "sim/sim_object.hh" class Event; @@ -59,7 +63,7 @@ class PioPort : public SimpleTimingPort virtual Tick recvAtomic(PacketPtr pkt); virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop); + bool &snoop); public: @@ -70,7 +74,7 @@ class PioPort : public SimpleTimingPort class DmaPort : public Port { protected: - struct DmaReqState : public Packet::SenderState + struct DmaReqState : public Packet::SenderState, public FastAlloc { /** Event to call on the device when this transaction (all packets) * complete. */ @@ -85,12 +89,17 @@ class DmaPort : public Port /** 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) + /** Amount to delay completion of dma by */ + Tick delay; + + + DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay) + : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0), + delay(_delay) {} }; - DmaDevice *device; + MemObject *device; std::list transmitList; /** The system that device/port are in. This is used to select which mode @@ -107,32 +116,76 @@ class DmaPort : public Port * here.*/ Event *drainEvent; + /** time to wait between sending another packet, increases as NACKs are + * recived, decreases as responses are recived. */ + Tick backoffTime; + + /** Minimum time that device should back off for after failed sendTiming */ + Tick minBackoffDelay; + + /** Maximum time that device should back off for after failed sendTiming */ + Tick maxBackoffDelay; + + /** If the port is currently waiting for a retry before it can send whatever + * it is that it's sending. */ + bool inRetry; + + /** Port accesses a cache which requires snooping */ + bool recvSnoops; + + /** Records snoop response so we only reply once to a status change */ + bool snoopRangeSent; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt) - { panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN } + { + if (recvSnoops) return 0; + + 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."); } + { + if (recvSnoops) return; + + panic("dma port shouldn't be used for pio access."); + } virtual void recvStatusChange(Status status) - { ; } + { + if (recvSnoops) { + if (status == RangeChange) { + if (!snoopRangeSent) { + snoopRangeSent = true; + sendStatusChange(Port::RangeChange); + } + return; + } + panic("Unexpected recvStatusChange\n"); + } + } virtual void recvRetry() ; virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + bool &snoop) + { resp.clear(); snoop = recvSnoops; } + + void queueDma(PacketPtr pkt, bool front = false); + void sendDma(); - void sendDma(PacketPtr pkt, bool front = false); + /** event to give us a kick every time we backoff time is reached. */ + EventWrapper backoffEvent; public: - DmaPort(DmaDevice *dev, System *s); + DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff, + bool recv_snoops = false); void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, - uint8_t *data = NULL); + uint8_t *data, Tick delay, Request::Flags flag = 0); bool dmaPending() { return pendingCount > 0; } - int cacheBlockSize() { return peerBlockSize(); } + unsigned cacheBlockSize() const { return peerBlockSize(); } unsigned int drain(Event *de); }; @@ -174,56 +227,28 @@ 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(); + const Params * + params() const + { + return dynamic_cast(_params); + } + virtual void init(); virtual unsigned int drain(Event *de); - 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 - return NULL; - } + virtual Port *getPort(const std::string &if_name, int idx = -1); + 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,10 +260,14 @@ class BasicPioDevice : public PioDevice Tick pioDelay; public: - BasicPioDevice(Params *p) - : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), - pioDelay(p->pio_delay) - {} + typedef BasicPioDeviceParams Params; + BasicPioDevice(const Params *p); + + const Params * + params() const + { + return dynamic_cast(_params); + } /** return the address ranges that this device responds to. * @param range_list range list to populate with ranges @@ -249,45 +278,37 @@ class BasicPioDevice : public PioDevice class DmaDevice : public PioDevice { - protected: + protected: DmaPort *dmaPort; public: - DmaDevice(Params *p); + typedef DmaDeviceParams Params; + DmaDevice(const Params *p); virtual ~DmaDevice(); - void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) + const Params * + params() const { - dmaPort->dmaAction(MemCmd::WriteInvalidateReq, - addr, size, event, data); + return dynamic_cast(_params); } - void dmaRead(Addr addr, int size, Event *event, uint8_t *data) + void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) { - dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data); + dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); + } + + void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) + { + dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); } bool dmaPending() { return dmaPort->dmaPending(); } virtual unsigned int drain(Event *de); - int cacheBlockSize() { return dmaPort->cacheBlockSize(); } + unsigned cacheBlockSize() const { 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; - } + virtual Port *getPort(const std::string &if_name, int idx = -1); friend class DmaPort; };