i8254xgbe.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 654 行 · 第 1/2 页

HH
654
字号
            DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n",                    descBase() + cachePnt * sizeof(T),                    igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),                    curFetching * sizeof(T));            assert(curFetching);            igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),                    curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf);        }        /** Called by event when dma to read descriptors is completed         */        void fetchComplete()        {            T *newDesc;            for (int x = 0; x < curFetching; x++) {                newDesc = new T;                memcpy(newDesc, &fetchBuf[x], sizeof(T));                unusedCache.push_back(newDesc);            }#ifndef NDEBUG            int oldCp = cachePnt;#endif            cachePnt += curFetching;            assert(cachePnt <= descLen());            if (cachePnt == descLen())                cachePnt = 0;            curFetching = 0;            DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n",                    oldCp, cachePnt);            enableSm();            igbe->checkDrain();        }        EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;        /** Called by event when dma to writeback descriptors is completed         */        void wbComplete()        {            long  curHead = descHead();#ifndef NDEBUG            long oldHead = curHead;#endif            curHead += wbOut;            wbOut = 0;            if (curHead >= descLen())                curHead -= descLen();            // Update the head            updateHead(curHead);            DPRINTF(EthernetDesc, "Writeback complete curHead %d -> %d\n",                    oldHead, curHead);            // If we still have more to wb, call wb now            intAfterWb();            if (moreToWb) {                DPRINTF(EthernetDesc, "Writeback has more todo\n");                writeback(wbAlignment);            }            if (!wbOut) {                igbe->checkDrain();            }            fetchAfterWb();        }        EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;        /* Return the number of descriptors left in the ring, so the device has         * a way to figure out if it needs to interrupt.         */        int descLeft() const        {            int left = unusedCache.size();            if (cachePnt - descTail() >= 0)                left += (cachePnt - descTail());            else                left += (descTail() - cachePnt);            return left;        }        /* Return the number of descriptors used and not written back.         */        int descUsed() const { return usedCache.size(); }        /* Return the number of cache unused descriptors we have. */        int descUnused() const {return unusedCache.size(); }        /* Get into a state where the descriptor address/head/etc colud be         * changed */        void reset()        {            DPRINTF(EthernetDesc, "Reseting descriptor cache\n");            for (int x = 0; x < usedCache.size(); x++)                delete usedCache[x];            for (int x = 0; x < unusedCache.size(); x++)                delete unusedCache[x];            usedCache.clear();            unusedCache.clear();            cachePnt = 0;        }        virtual void serialize(std::ostream &os)        {            SERIALIZE_SCALAR(cachePnt);            SERIALIZE_SCALAR(curFetching);            SERIALIZE_SCALAR(wbOut);            SERIALIZE_SCALAR(moreToWb);            SERIALIZE_SCALAR(wbAlignment);            int usedCacheSize = usedCache.size();            SERIALIZE_SCALAR(usedCacheSize);            for(int x = 0; x < usedCacheSize; x++) {                arrayParamOut(os, csprintf("usedCache_%d", x),                        (uint8_t*)usedCache[x],sizeof(T));            }            int unusedCacheSize = unusedCache.size();            SERIALIZE_SCALAR(unusedCacheSize);            for(int x = 0; x < unusedCacheSize; x++) {                arrayParamOut(os, csprintf("unusedCache_%d", x),                        (uint8_t*)unusedCache[x],sizeof(T));            }        }        virtual void unserialize(Checkpoint *cp, const std::string &section)        {            UNSERIALIZE_SCALAR(cachePnt);            UNSERIALIZE_SCALAR(curFetching);            UNSERIALIZE_SCALAR(wbOut);            UNSERIALIZE_SCALAR(moreToWb);            UNSERIALIZE_SCALAR(wbAlignment);            int usedCacheSize;            UNSERIALIZE_SCALAR(usedCacheSize);            T *temp;            for(int x = 0; x < usedCacheSize; x++) {                temp = new T;                arrayParamIn(cp, section, csprintf("usedCache_%d", x),                        (uint8_t*)temp,sizeof(T));                usedCache.push_back(temp);            }            int unusedCacheSize;            UNSERIALIZE_SCALAR(unusedCacheSize);            for(int x = 0; x < unusedCacheSize; x++) {                temp = new T;                arrayParamIn(cp, section, csprintf("unusedCache_%d", x),                        (uint8_t*)temp,sizeof(T));                unusedCache.push_back(temp);            }        }        virtual bool hasOutstandingEvents() {            return wbEvent.scheduled() || fetchEvent.scheduled();        }     };    class RxDescCache : public DescCache<iGbReg::RxDesc>    {      protected:        virtual Addr descBase() const { return igbe->regs.rdba(); }        virtual long descHead() const { return igbe->regs.rdh(); }        virtual long descLen() const { return igbe->regs.rdlen() >> 4; }        virtual long descTail() const { return igbe->regs.rdt(); }        virtual void updateHead(long h) { igbe->regs.rdh(h); }        virtual void enableSm();        virtual void fetchAfterWb() {            if (!igbe->rxTick && igbe->getState() == SimObject::Running)                fetchDescriptors();        }        bool pktDone;      public:        RxDescCache(IGbE *i, std::string n, int s);        /** Write the given packet into the buffer(s) pointed to by the         * descriptor and update the book keeping. Should only be called when         * there are no dma's pending.         * @param packet ethernet packet to write         * @return if the packet could be written (there was a free descriptor)         */        void writePacket(EthPacketPtr packet);        /** Called by event when dma to write packet is completed         */        void pktComplete();        /** Check if the dma on the packet has completed.         */        bool packetDone();        EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;        virtual bool hasOutstandingEvents();        virtual void serialize(std::ostream &os);        virtual void unserialize(Checkpoint *cp, const std::string &section);    };    friend class RxDescCache;    RxDescCache rxDescCache;    class TxDescCache  : public DescCache<iGbReg::TxDesc>    {      protected:        virtual Addr descBase() const { return igbe->regs.tdba(); }        virtual long descHead() const { return igbe->regs.tdh(); }        virtual long descTail() const { return igbe->regs.tdt(); }        virtual long descLen() const { return igbe->regs.tdlen() >> 4; }        virtual void updateHead(long h) { igbe->regs.tdh(h); }        virtual void enableSm();        virtual void intAfterWb() const { igbe->postInterrupt(iGbReg::IT_TXDW); }        virtual void fetchAfterWb() {            if (!igbe->txTick && igbe->getState() == SimObject::Running)                fetchDescriptors();        }        bool pktDone;        bool isTcp;        bool pktWaiting;      public:        TxDescCache(IGbE *i, std::string n, int s);        /** Tell the cache to DMA a packet from main memory into its buffer and         * return the size the of the packet to reserve space in tx fifo.         * @return size of the packet         */        int getPacketSize();        void getPacketData(EthPacketPtr p);        /** Ask if the packet has been transfered so the state machine can give         * it to the fifo.         * @return packet available in descriptor cache         */        bool packetAvailable();        /** Ask if we are still waiting for the packet to be transfered.         * @return packet still in transit.         */        bool packetWaiting() { return pktWaiting; }        /** Called by event when dma to write packet is completed         */        void pktComplete();        EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;        virtual bool hasOutstandingEvents();        virtual void serialize(std::ostream &os);        virtual void unserialize(Checkpoint *cp, const std::string &section);    };    friend class TxDescCache;    TxDescCache txDescCache;  public:    typedef IGbEParams Params;    const Params *    params() const    {        return dynamic_cast<const Params *>(_params);    }    IGbE(const Params *params);    ~IGbE() {}    virtual EtherInt *getEthPort(const std::string &if_name, int idx);    Tick clock;    inline Tick ticks(int numCycles) const { return numCycles * clock; }    virtual Tick read(PacketPtr pkt);    virtual Tick write(PacketPtr pkt);    virtual Tick writeConfig(PacketPtr pkt);    bool ethRxPkt(EthPacketPtr packet);    void ethTxDone();    virtual void serialize(std::ostream &os);    virtual void unserialize(Checkpoint *cp, const std::string &section);    virtual unsigned int drain(Event *de);    virtual void resume();};class IGbEInt : public EtherInt{  private:    IGbE *dev;  public:    IGbEInt(const std::string &name, IGbE *d)        : EtherInt(name), dev(d)    { }    virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }    virtual void sendDone() { dev->ethTxDone(); }};#endif //__DEV_I8254XGBE_HH__

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?