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 §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); } } 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 §ion); }; 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 §ion); }; 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 §ion); 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 + -
显示快捷键?