X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fi8254xGBe.hh;h=f7f7d9a2adaa03acb9bc7e5eda60912bb0bbd53f;hb=da3c3bfa98e7cf81010a476b0b6ceba4c936f417;hp=4c3896e36c57b1c198de72607e6557111b51155d;hpb=3d5fe0c372a16f9178b348080c1c1bb24dd1d834;p=gem5.git diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 4c3896e36..f7f7d9a2a 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -38,6 +38,7 @@ #include #include +#include "base/cp_annotate.hh" #include "base/inet.hh" #include "dev/etherdevice.hh" #include "dev/etherint.hh" @@ -54,6 +55,7 @@ class IGbE : public EtherDevice { private: IGbEInt *etherInt; + CPA *cpa; // device registers iGbReg::Regs regs; @@ -83,6 +85,9 @@ class IGbE : public EtherDevice bool rxDmaPacket; + // Number of bytes copied from current RX packet + unsigned pktOffset; + // Delays in managaging descriptors Tick fetchDelay, wbDelay; Tick fetchCompDelay, wbCompDelay; @@ -91,7 +96,8 @@ class IGbE : public EtherDevice // Event and function to deal with RDTR timer expiring void rdtrProcess() { rxDescCache.writeback(0); - DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n"); + DPRINTF(EthernetIntr, + "Posting RXT interrupt because RDTR timer expired\n"); postInterrupt(iGbReg::IT_RXT); } @@ -101,7 +107,8 @@ class IGbE : public EtherDevice // Event and function to deal with RADV timer expiring void radvProcess() { rxDescCache.writeback(0); - DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n"); + DPRINTF(EthernetIntr, + "Posting RXT interrupt because RADV timer expired\n"); postInterrupt(iGbReg::IT_RXT); } @@ -111,7 +118,8 @@ class IGbE : public EtherDevice // Event and function to deal with TADV timer expiring void tadvProcess() { txDescCache.writeback(0); - DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n"); + DPRINTF(EthernetIntr, + "Posting TXDW interrupt because TADV timer expired\n"); postInterrupt(iGbReg::IT_TXDW); } @@ -121,7 +129,8 @@ class IGbE : public EtherDevice // Event and function to deal with TIDV timer expiring void tidvProcess() { txDescCache.writeback(0); - DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n"); + DPRINTF(EthernetIntr, + "Posting TXDW interrupt because TIDV timer expired\n"); postInterrupt(iGbReg::IT_TXDW); } //friend class EventWrapper; @@ -173,6 +182,35 @@ class IGbE : public EtherDevice */ void checkDrain(); + void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) { + cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st); + } + + void anQ(std::string sm, std::string q) { + cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anDq(std::string sm, std::string q) { + cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anPq(std::string sm, std::string q, int num = 1) { + cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); + } + + void anRq(std::string sm, std::string q, int num = 1) { + cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); + } + + void anWe(std::string sm, std::string q) { + cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anWf(std::string sm, std::string q) { + cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + template class DescCache { @@ -183,11 +221,12 @@ class IGbE : public EtherDevice virtual long descLen() const = 0; virtual void updateHead(long h) = 0; virtual void enableSm() = 0; - virtual void intAfterWb() const {} + virtual void actionAfterWb() {} virtual void fetchAfterWb() = 0; - std::deque usedCache; - std::deque unusedCache; + typedef std::deque CacheType; + CacheType usedCache; + CacheType unusedCache; T *fetchBuf; T *wbBuf; @@ -217,24 +256,19 @@ class IGbE : public EtherDevice // What the alignment is of the next descriptor writeback Addr wbAlignment; - /** The packet that is currently being dmad to memory if any - */ + /** The packet that is currently being dmad to memory if any */ EthPacketPtr pktPtr; + /** Shortcut for DMA address translation */ + Addr pciToDma(Addr a) { return igbe->platform->pciToDma(a); } + public: - DescCache(IGbE *i, const std::string n, int s) - : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0), - pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this), - fetchEvent(this), wbEvent(this) - { - fetchBuf = new T[size]; - wbBuf = new T[size]; - } + /** Annotate sm*/ + std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ, + annUsedDescQ, annUnusedCacheQ, annDescQ; - virtual ~DescCache() - { - reset(); - } + DescCache(IGbE *i, const std::string n, int s); + virtual ~DescCache(); std::string name() { return _name; } @@ -242,228 +276,38 @@ class IGbE : public EtherDevice * dirty that is very bad. This function checks that we don't and if we * do panics. */ - void areaChanged() - { - if (usedCache.size() > 0 || curFetching || wbOut) - panic("Descriptor Address, Length or Head changed. Bad\n"); - reset(); - - } + void areaChanged(); - void writeback(Addr aMask) - { - int curHead = descHead(); - int max_to_wb = usedCache.size(); - - // Check if this writeback is less restrictive that the previous - // and if so setup another one immediately following it - if (wbOut) { - if (aMask < wbAlignment) { - moreToWb = true; - wbAlignment = aMask; - } - DPRINTF(EthernetDesc, "Writing back already in process, returning\n"); - return; - } - - moreToWb = false; - wbAlignment = aMask; - - - DPRINTF(EthernetDesc, "Writing back descriptors head: %d tail: " - "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n", - curHead, descTail(), descLen(), cachePnt, max_to_wb, - descLeft()); - - if (max_to_wb + curHead >= descLen()) { - max_to_wb = descLen() - curHead; - moreToWb = true; - // this is by definition aligned correctly - } else if (wbAlignment != 0) { - // align the wb point to the mask - max_to_wb = max_to_wb & ~wbAlignment; - } - - DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb); - - if (max_to_wb <= 0) { - return; - } - - wbOut = max_to_wb; - - assert(!wbDelayEvent.scheduled()); - wbDelayEvent.schedule(igbe->wbDelay + curTick); - } - - void writeback1() - { - // If we're draining delay issuing this DMA - if (igbe->drainEvent) { - wbDelayEvent.schedule(igbe->wbDelay + curTick); - return; - } - - DPRINTF(EthernetDesc, "Beining DMA of %d descriptors\n", wbOut); - - for (int x = 0; x < wbOut; x++) { - assert(usedCache.size()); - memcpy(&wbBuf[x], usedCache[x], sizeof(T)); - //delete usedCache[0]; - //usedCache.pop_front(); - } - - assert(wbOut); - igbe->dmaWrite(igbe->platform->pciToDma(descBase() + descHead() * sizeof(T)), - wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf, - igbe->wbCompDelay); - } + void writeback(Addr aMask); + void writeback1(); EventWrapper wbDelayEvent; /** Fetch a chunk of descriptors into the descriptor cache. * Calls fetchComplete when the memory system returns the data */ - - void fetchDescriptors() - { - size_t max_to_fetch; - - if (curFetching) { - DPRINTF(EthernetDesc, "Currently fetching %d descriptors, returning\n", curFetching); - return; - } - - if (descTail() >= cachePnt) - max_to_fetch = descTail() - cachePnt; - else - max_to_fetch = descLen() - cachePnt; - - size_t free_cache = size - usedCache.size() - unusedCache.size(); - - max_to_fetch = std::min(max_to_fetch, free_cache); - - - DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: " - "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n", - descHead(), descTail(), descLen(), cachePnt, - max_to_fetch, descLeft()); - - // Nothing to do - if (max_to_fetch == 0) - return; - - // So we don't have two descriptor fetches going on at once - curFetching = max_to_fetch; - - assert(!fetchDelayEvent.scheduled()); - fetchDelayEvent.schedule(igbe->fetchDelay + curTick); - } - - void fetchDescriptors1() - { - // If we're draining delay issuing this DMA - if (igbe->drainEvent) { - fetchDelayEvent.schedule(igbe->fetchDelay + curTick); - return; - } - - 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, - igbe->fetchCompDelay); - } - + void fetchDescriptors(); + void fetchDescriptors1(); EventWrapper fetchDelayEvent; /** 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(); - } - + void fetchComplete(); EventWrapper fetchEvent; /** Called by event when dma to writeback descriptors is completed */ - void wbComplete() - { - - long curHead = descHead(); -#ifndef NDEBUG - long oldHead = curHead; -#endif - - for (int x = 0; x < wbOut; x++) { - assert(usedCache.size()); - delete usedCache[0]; - usedCache.pop_front(); - } - - 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) { - moreToWb = false; - DPRINTF(EthernetDesc, "Writeback has more todo\n"); - writeback(wbAlignment); - } - - if (!wbOut) { - igbe->checkDrain(); - } - fetchAfterWb(); - } - - + void wbComplete(); EventWrapper 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 + unsigned + descLeft() const { - int left = unusedCache.size(); - if (cachePnt - descTail() >= 0) - left += (cachePnt - descTail()); + unsigned left = unusedCache.size(); + if (cachePnt > descTail()) + left += (descLen() - cachePnt + descTail()); else left += (descTail() - cachePnt); @@ -472,102 +316,23 @@ class IGbE : public EtherDevice /* Return the number of descriptors used and not written back. */ - int descUsed() const { return usedCache.size(); } + unsigned descUsed() const { return usedCache.size(); } /* Return the number of cache unused descriptors we have. */ - int descUnused() const {return unusedCache.size(); } + unsigned 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)); - } - - Tick fetch_delay = 0, wb_delay = 0; - if (fetchDelayEvent.scheduled()) - fetch_delay = fetchDelayEvent.when(); - SERIALIZE_SCALAR(fetch_delay); - if (wbDelayEvent.scheduled()) - wb_delay = wbDelayEvent.when(); - SERIALIZE_SCALAR(wb_delay); - - - } - - virtual void unserialize(Checkpoint *cp, const std::string §ion) - { - 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); - } - Tick fetch_delay = 0, wb_delay = 0; - UNSERIALIZE_SCALAR(fetch_delay); - UNSERIALIZE_SCALAR(wb_delay); - if (fetch_delay) - fetchDelayEvent.schedule(fetch_delay); - if (wb_delay) - wbDelayEvent.schedule(wb_delay); + void reset(); + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); - } virtual bool hasOutstandingEvents() { return wbEvent.scheduled() || fetchEvent.scheduled(); } - }; + }; class RxDescCache : public DescCache @@ -586,6 +351,13 @@ class IGbE : public EtherDevice bool pktDone; + /** Variable to head with header/data completion events */ + int splitCount; + + /** Bytes of packet that have been copied, so we know when to + set EOP */ + unsigned bytesCopied; + public: RxDescCache(IGbE *i, std::string n, int s); @@ -593,20 +365,28 @@ class IGbE : public EtherDevice * 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) + * @param pkt_offset bytes already copied from the packet to memory + * @return pkt_offset + number of bytes copied during this call */ - void writePacket(EthPacketPtr packet); + int writePacket(EthPacketPtr packet, int pkt_offset); + /** Called by event when dma to write packet is completed */ void pktComplete(); - /** Check if the dma on the packet has completed. + /** Check if the dma on the packet has completed and RX state machine + * can continue */ - bool packetDone(); EventWrapper pktEvent; + // Event to handle issuing header and data write at the same time + // and only callking pktComplete() when both are completed + void pktSplitDone(); + EventWrapper pktHdrEvent; + EventWrapper pktDataEvent; + virtual bool hasOutstandingEvents(); virtual void serialize(std::ostream &os); @@ -625,16 +405,37 @@ class IGbE : public EtherDevice 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 actionAfterWb(); virtual void fetchAfterWb() { if (!igbe->txTick && igbe->getState() == SimObject::Running) fetchDescriptors(); } + + bool pktDone; bool isTcp; bool pktWaiting; bool pktMultiDesc; + Addr completionAddress; + bool completionEnabled; + uint32_t descEnd; + + + // tso variables + bool useTso; + Addr tsoHeaderLen; + Addr tsoMss; + Addr tsoTotalLen; + Addr tsoUsedLen; + Addr tsoPrevSeq;; + Addr tsoPktPayloadBytes; + bool tsoLoadedHeader; + bool tsoPktHasHeader; + uint8_t tsoHeader[256]; + Addr tsoDescBytesUsed; + Addr tsoCopyBytes; + int tsoPkts; public: TxDescCache(IGbE *i, std::string n, int s); @@ -643,8 +444,18 @@ class IGbE : public EtherDevice * return the size the of the packet to reserve space in tx fifo. * @return size of the packet */ - int getPacketSize(); + unsigned getPacketSize(EthPacketPtr p); void getPacketData(EthPacketPtr p); + void processContextDesc(); + + /** Return the number of dsecriptors in a cache block for threshold + * operations. + */ + unsigned + descInBlock(unsigned num_desc) + { + return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); + } /** Ask if the packet has been transfered so the state machine can give * it to the fifo. @@ -670,8 +481,25 @@ class IGbE : public EtherDevice void pktComplete(); EventWrapper pktEvent; + void headerComplete(); + EventWrapper headerEvent; + + + void completionWriteback(Addr a, bool enabled) { + DPRINTF(EthernetDesc, + "Completion writeback Addr: %#x enabled: %d\n", + a, enabled); + completionAddress = a; + completionEnabled = enabled; + } + virtual bool hasOutstandingEvents(); + void nullCallback() { + DPRINTF(EthernetDesc, "Completion writeback complete\n"); + } + EventWrapper nullEvent; + virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); @@ -683,12 +511,13 @@ class IGbE : public EtherDevice public: typedef IGbEParams Params; const Params * - params() const - { + params() const { return dynamic_cast(_params); } + IGbE(const Params *params); ~IGbE() {} + virtual void init(); virtual EtherInt *getEthPort(const std::string &if_name, int idx); @@ -725,9 +554,4 @@ class IGbEInt : public EtherInt virtual void sendDone() { dev->ethTxDone(); } }; - - - - #endif //__DEV_I8254XGBE_HH__ -