i8254xgbe.cc

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

CC
1,528
字号
                        igbe->intClock(), true);        }        if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {            DPRINTF(EthernetDesc, "setting tadv\n");            if (!igbe->tadvEvent.scheduled()) {                igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() *                        igbe->intClock());            }        }    }    unusedCache.pop_front();    usedCache.push_back(desc);    pktDone = true;    pktWaiting = false;    pktPtr = NULL;    DPRINTF(EthernetDesc, "Descriptor Done\n");    if (igbe->regs.txdctl.wthresh() == 0) {        DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");        writeback(0);    } else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {        DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");        writeback((igbe->cacheBlockSize()-1)>>4);    }    enableSm();    igbe->checkDrain();}voidIGbE::TxDescCache::serialize(std::ostream &os){    DescCache<TxDesc>::serialize(os);    SERIALIZE_SCALAR(pktDone);    SERIALIZE_SCALAR(isTcp);    SERIALIZE_SCALAR(pktWaiting);}voidIGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string &section){    DescCache<TxDesc>::unserialize(cp, section);    UNSERIALIZE_SCALAR(pktDone);    UNSERIALIZE_SCALAR(isTcp);    UNSERIALIZE_SCALAR(pktWaiting);}boolIGbE::TxDescCache::packetAvailable(){    if (pktDone) {        pktDone = false;        return true;    }    return false;}voidIGbE::TxDescCache::enableSm(){    if (!igbe->drainEvent) {        igbe->txTick = true;        igbe->restartClock();    }}boolIGbE::TxDescCache::hasOutstandingEvents(){    return pktEvent.scheduled() || wbEvent.scheduled() ||        fetchEvent.scheduled();}///////////////////////////////////// IGbE /////////////////////////////////voidIGbE::restartClock(){    if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && getState() ==            SimObject::Running)        tickEvent.schedule((curTick/ticks(1)) * ticks(1) + ticks(1));}unsigned intIGbE::drain(Event *de){    unsigned int count;    count = pioPort->drain(de) + dmaPort->drain(de);    if (rxDescCache.hasOutstandingEvents() ||            txDescCache.hasOutstandingEvents()) {        count++;        drainEvent = de;    }    txFifoTick = false;    txTick = false;    rxTick = false;    if (tickEvent.scheduled())        tickEvent.deschedule();    if (count)        changeState(Draining);    else        changeState(Drained);    return count;}voidIGbE::resume(){    SimObject::resume();    txFifoTick = true;    txTick = true;    rxTick = true;    restartClock();}voidIGbE::checkDrain(){    if (!drainEvent)        return;    txFifoTick = false;    txTick = false;    rxTick = false;    if (!rxDescCache.hasOutstandingEvents() &&            !txDescCache.hasOutstandingEvents()) {        drainEvent->process();        drainEvent = NULL;    }}voidIGbE::txStateMachine(){    if (!regs.tctl.en()) {        txTick = false;        DPRINTF(EthernetSM, "TXS: TX disabled, stopping ticking\n");        return;    }    // If we have a packet available and it's length is not 0 (meaning it's not    // a multidescriptor packet) put it in the fifo, otherwise an the next    // iteration we'll get the rest of the data    if (txPacket && txDescCache.packetAvailable() && txPacket->length) {        bool success;        DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");        success = txFifo.push(txPacket);        txFifoTick = true && !drainEvent;        assert(success);        txPacket = NULL;        txDescCache.writeback((cacheBlockSize()-1)>>4);        return;    }    // Only support descriptor granularity    assert(regs.txdctl.gran());    if (regs.txdctl.lwthresh() && txDescCache.descLeft() < (regs.txdctl.lwthresh() * 8)) {        DPRINTF(EthernetSM, "TXS: LWTHRESH caused posting of TXDLOW\n");        postInterrupt(IT_TXDLOW);    }    if (!txPacket) {        txPacket = new EthPacketData(16384);    }    if (!txDescCache.packetWaiting()) {        if (txDescCache.descLeft() == 0) {            postInterrupt(IT_TXQE);            txDescCache.writeback(0);            txDescCache.fetchDescriptors();            DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing "                    "writeback stopping ticking and posting TXQE\n");            txTick = false;            return;        }        if (!(txDescCache.descUnused())) {            txDescCache.fetchDescriptors();            DPRINTF(EthernetSM, "TXS: No descriptors available in cache, fetching and stopping ticking\n");            txTick = false;            return;        }        int size;        size = txDescCache.getPacketSize();        if (size > 0 && txFifo.avail() > size) {            DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining "                    "DMA of next packet\n", size);            txFifo.reserve(size);            txDescCache.getPacketData(txPacket);        } else if (size <= 0) {            DPRINTF(EthernetSM, "TXS: getPacketSize returned: %d\n", size);            DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");            txDescCache.writeback(0);        } else {            DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "                    "available in FIFO\n");            txTick = false;        }        return;    }    DPRINTF(EthernetSM, "TXS: Nothing to do, stopping ticking\n");    txTick = false;}boolIGbE::ethRxPkt(EthPacketPtr pkt){    DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n");    if (!regs.rctl.en()) {        DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n");        return true;    }    // restart the state machines if they are stopped    rxTick = true && !drainEvent;    if ((rxTick || txTick) && !tickEvent.scheduled()) {        DPRINTF(EthernetSM, "RXS: received packet into fifo, starting ticking\n");        restartClock();    }    if (!rxFifo.push(pkt)) {        DPRINTF(Ethernet, "RxFIFO: Packet won't fit in fifo... dropped\n");        postInterrupt(IT_RXO, true);        return false;    }    return true;}voidIGbE::rxStateMachine(){    if (!regs.rctl.en()) {        rxTick = false;        DPRINTF(EthernetSM, "RXS: RX disabled, stopping ticking\n");        return;    }    // If the packet is done check for interrupts/descriptors/etc    if (rxDescCache.packetDone()) {        rxDmaPacket = false;        DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n");        int descLeft = rxDescCache.descLeft();        switch (regs.rctl.rdmts()) {            case 2: if (descLeft > .125 * regs.rdlen()) break;            case 1: if (descLeft > .250 * regs.rdlen()) break;            case 0: if (descLeft > .500 * regs.rdlen())  break;                DPRINTF(Ethernet, "RXS: Interrupting (RXDMT) because of descriptors left\n");                postInterrupt(IT_RXDMT);                break;        }        if (descLeft == 0) {            rxDescCache.writeback(0);            DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"                    " writeback and stopping ticking\n");            rxTick = false;        }        // only support descriptor granulaties        assert(regs.rxdctl.gran());        if (regs.rxdctl.wthresh() >= rxDescCache.descUsed()) {            DPRINTF(EthernetSM, "RXS: Writing back because WTHRESH >= descUsed\n");            if (regs.rxdctl.wthresh() < (cacheBlockSize()>>4))                rxDescCache.writeback(regs.rxdctl.wthresh()-1);            else                rxDescCache.writeback((cacheBlockSize()-1)>>4);        }        if ((rxDescCache.descUnused() < regs.rxdctl.pthresh()) &&             ((rxDescCache.descLeft() - rxDescCache.descUnused()) > regs.rxdctl.hthresh())) {            DPRINTF(EthernetSM, "RXS: Fetching descriptors because descUnused < PTHRESH\n");            rxDescCache.fetchDescriptors();        }        if (rxDescCache.descUnused() == 0) {            rxDescCache.fetchDescriptors();            DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "                    "fetching descriptors and stopping ticking\n");            rxTick = false;        }        return;    }    if (rxDmaPacket) {        DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");        rxTick = false;        return;    }    if (!rxDescCache.descUnused()) {        rxDescCache.fetchDescriptors();        DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");        rxTick = false;        DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n");        return;    }    if (rxFifo.empty()) {        DPRINTF(EthernetSM, "RXS: RxFIFO empty, stopping ticking\n");        rxTick = false;        return;    }    EthPacketPtr pkt;    pkt = rxFifo.front();    rxDescCache.writePacket(pkt);    DPRINTF(EthernetSM, "RXS: Writing packet into memory\n");    DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n");    rxFifo.pop();    DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");    rxTick = false;    rxDmaPacket = true;}voidIGbE::txWire(){    if (txFifo.empty()) {        txFifoTick = false;        return;    }    if (etherInt->sendPacket(txFifo.front())) {        if (DTRACE(EthernetSM)) {            IpPtr ip(txFifo.front());            if (ip)                DPRINTF(EthernetSM, "Transmitting Ip packet with Id=%d\n",                        ip->id());            else                DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n");        }        DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",                txFifo.avail());        txFifo.pop();    } else {        // We'll get woken up when the packet ethTxDone() gets called        txFifoTick = false;    }}voidIGbE::tick(){    DPRINTF(EthernetSM, "IGbE: -------------- Cycle --------------\n");    if (rxTick)        rxStateMachine();    if (txTick)        txStateMachine();    if (txFifoTick)        txWire();    if (rxTick || txTick || txFifoTick)        tickEvent.schedule(curTick + ticks(1));}voidIGbE::ethTxDone(){    // restart the tx state machines if they are stopped    // fifo to send another packet    // tx sm to put more data into the fifo    txFifoTick = true && !drainEvent;    if (txDescCache.descLeft() != 0 && !drainEvent)        txTick = true;    restartClock();    DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n");}voidIGbE::serialize(std::ostream &os){    PciDev::serialize(os);    regs.serialize(os);    SERIALIZE_SCALAR(eeOpBits);    SERIALIZE_SCALAR(eeAddrBits);    SERIALIZE_SCALAR(eeDataBits);    SERIALIZE_SCALAR(eeOpcode);    SERIALIZE_SCALAR(eeAddr);    SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);    rxFifo.serialize("rxfifo", os);    txFifo.serialize("txfifo", os);    bool txPktExists = txPacket;    SERIALIZE_SCALAR(txPktExists);    if (txPktExists)        txPacket->serialize("txpacket", os);    Tick rdtr_time = 0, radv_time = 0, tidv_time = 0, tadv_time = 0,         inter_time = 0;    if (rdtrEvent.scheduled())       rdtr_time = rdtrEvent.when();    SERIALIZE_SCALAR(rdtr_time);    if (radvEvent.scheduled())       radv_time = radvEvent.when();    SERIALIZE_SCALAR(radv_time);    if (tidvEvent.scheduled())       tidv_time = tidvEvent.when();    SERIALIZE_SCALAR(tidv_time);    if (tadvEvent.scheduled())       tadv_time = tadvEvent.when();    SERIALIZE_SCALAR(tadv_time);    if (interEvent.scheduled())       inter_time = interEvent.when();    SERIALIZE_SCALAR(inter_time);    nameOut(os, csprintf("%s.TxDescCache", name()));    txDescCache.serialize(os);    nameOut(os, csprintf("%s.RxDescCache", name()));    rxDescCache.serialize(os);}voidIGbE::unserialize(Checkpoint *cp, const std::string &section){    PciDev::unserialize(cp, section);    regs.unserialize(cp, section);    UNSERIALIZE_SCALAR(eeOpBits);    UNSERIALIZE_SCALAR(eeAddrBits);    UNSERIALIZE_SCALAR(eeDataBits);    UNSERIALIZE_SCALAR(eeOpcode);    UNSERIALIZE_SCALAR(eeAddr);    UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);    rxFifo.unserialize("rxfifo", cp, section);    txFifo.unserialize("txfifo", cp, section);    bool txPktExists;    UNSERIALIZE_SCALAR(txPktExists);    if (txPktExists) {        txPacket = new EthPacketData(16384);        txPacket->unserialize("txpacket", cp, section);    }    rxTick = true;    txTick = true;    txFifoTick = true;    Tick rdtr_time, radv_time, tidv_time, tadv_time, inter_time;    UNSERIALIZE_SCALAR(rdtr_time);    UNSERIALIZE_SCALAR(radv_time);    UNSERIALIZE_SCALAR(tidv_time);    UNSERIALIZE_SCALAR(tadv_time);    UNSERIALIZE_SCALAR(inter_time);    if (rdtr_time)        rdtrEvent.schedule(rdtr_time);    if (radv_time)        radvEvent.schedule(radv_time);    if (tidv_time)        tidvEvent.schedule(tidv_time);    if (tadv_time)        tadvEvent.schedule(tadv_time);    if (inter_time)        interEvent.schedule(inter_time);    txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section));    rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section));}IGbE *IGbEParams::create(){    return new IGbE(this);}

⌨️ 快捷键说明

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