sinic.cc

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

CC
1,617
字号
  reschedule:   if (!txFifo.empty() && !txEvent.scheduled()) {       DPRINTF(Ethernet, "reschedule transmit\n");       txEvent.schedule(curTick + retryTime);   }}voidDevice::txKick(){    VirtualReg *vnic;    DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n",            TxStateStrings[txState], txFifo.size());    if (txKickTick > curTick) {        DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n",                txKickTick);        return;    }  next:    if (txState == txIdle)        goto exit;    assert(!txList.empty());    vnic = &virtualRegs[txList.front()];    switch (txState) {      case txFifoBlock:        assert(Regs::get_TxDone_Busy(vnic->TxDone));        if (!txPacket) {            // Grab a new packet from the fifo.            txPacket = new EthPacketData(16384);            txPacketOffset = 0;        }        if (txFifo.avail() - txPacket->length <            Regs::get_TxData_Len(vnic->TxData)) {            DPRINTF(EthernetSM, "transmit fifo full.  Nothing to do.\n");            goto exit;        }        txState = txBeginCopy;        break;      case txBeginCopy:        if (dmaPending() || getState() != Running)            goto exit;        txDmaAddr = params()->platform->pciToDma(                Regs::get_TxData_Addr(vnic->TxData));        txDmaLen = Regs::get_TxData_Len(vnic->TxData);        txDmaData = txPacket->data + txPacketOffset;        txState = txCopy;        dmaRead(txDmaAddr, txDmaLen, &txDmaEvent, txDmaData);        break;      case txCopy:        DPRINTF(EthernetSM, "transmit machine still copying\n");        goto exit;      case txCopyDone:        vnic->TxDone = txDmaLen | Regs::TxDone_Complete;        txPacket->length += txDmaLen;        if ((vnic->TxData & Regs::TxData_More)) {            txPacketOffset += txDmaLen;            txState = txIdle;            devIntrPost(Regs::Intr_TxDMA);            break;        }        assert(txPacket->length <= txFifo.avail());        if ((vnic->TxData & Regs::TxData_Checksum)) {            IpPtr ip(txPacket);            if (ip) {                TcpPtr tcp(ip);                if (tcp) {                    tcp->sum(0);                    tcp->sum(cksum(tcp));                    txTcpChecksums++;                }                UdpPtr udp(ip);                if (udp) {                    udp->sum(0);                    udp->sum(cksum(udp));                    txUdpChecksums++;                }                ip->sum(0);                ip->sum(cksum(ip));                txIpChecksums++;            }        }        txFifo.push(txPacket);        if (txFifo.avail() < regs.TxMaxCopy) {            devIntrPost(Regs::Intr_TxFull);            txFull = true;        }        txPacket = 0;        transmit();        txList.pop_front();        txState = txList.empty() ? txIdle : txFifoBlock;        devIntrPost(Regs::Intr_TxDMA);        break;      default:        panic("Invalid txState!");    }    DPRINTF(EthernetSM, "entering next txState=%s\n",            TxStateStrings[txState]);    goto next;  exit:    /**     * @todo do we want to schedule a future kick?     */    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",            TxStateStrings[txState]);}voidDevice::transferDone(){    if (txFifo.empty()) {        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");        return;    }    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");    txEvent.reschedule(curTick + ticks(1), true);}boolDevice::rxFilter(const EthPacketPtr &packet){    if (!Regs::get_Config_Filter(regs.Config))        return false;    panic("receive filter not implemented\n");    bool drop = true;#if 0    string type;    EthHdr *eth = packet->eth();    if (eth->unicast()) {        // If we're accepting all unicast addresses        if (acceptUnicast)            drop = false;        // If we make a perfect match        if (acceptPerfect && params->eaddr == eth.dst())            drop = false;        if (acceptArp && eth->type() == ETH_TYPE_ARP)            drop = false;    } else if (eth->broadcast()) {        // if we're accepting broadcasts        if (acceptBroadcast)            drop = false;    } else if (eth->multicast()) {        // if we're accepting all multicasts        if (acceptMulticast)            drop = false;    }    if (drop) {        DPRINTF(Ethernet, "rxFilter drop\n");        DDUMP(EthernetData, packet->data, packet->length);    }#endif    return drop;}boolDevice::recvPacket(EthPacketPtr packet){    rxBytes += packet->length;    rxPackets++;    DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",            rxFifo.avail());    if (!rxEnable) {        DPRINTF(Ethernet, "receive disabled...packet dropped\n");        return true;    }    if (rxFilter(packet)) {        DPRINTF(Ethernet, "packet filtered...dropped\n");        return true;    }    if (rxFifo.size() >= regs.RxFifoMark)        devIntrPost(Regs::Intr_RxHigh);    if (!rxFifo.push(packet)) {        DPRINTF(Ethernet,                "packet will not fit in receive buffer...packet dropped\n");        return false;    }    // If we were at the last element, back up one ot go to the new    // last element of the list.    if (rxFifoPtr == rxFifo.end())        --rxFifoPtr;    devIntrPost(Regs::Intr_RxPacket);    rxKick();    return true;}voidDevice::resume(){    SimObject::resume();    // During drain we could have left the state machines in a waiting state and    // they wouldn't get out until some other event occured to kick them.    // This way they'll get out immediately    txKick();    rxKick();}//=====================================================================////voidBase::serialize(std::ostream &os){    // Serialize the PciDev base class    PciDev::serialize(os);    SERIALIZE_SCALAR(rxEnable);    SERIALIZE_SCALAR(txEnable);    SERIALIZE_SCALAR(cpuIntrEnable);    /*     * Keep track of pending interrupt status.     */    SERIALIZE_SCALAR(intrTick);    SERIALIZE_SCALAR(cpuPendingIntr);    Tick intrEventTick = 0;    if (intrEvent)        intrEventTick = intrEvent->when();    SERIALIZE_SCALAR(intrEventTick);}voidBase::unserialize(Checkpoint *cp, const std::string &section){    // Unserialize the PciDev base class    PciDev::unserialize(cp, section);    UNSERIALIZE_SCALAR(rxEnable);    UNSERIALIZE_SCALAR(txEnable);    UNSERIALIZE_SCALAR(cpuIntrEnable);    /*     * Keep track of pending interrupt status.     */    UNSERIALIZE_SCALAR(intrTick);    UNSERIALIZE_SCALAR(cpuPendingIntr);    Tick intrEventTick;    UNSERIALIZE_SCALAR(intrEventTick);    if (intrEventTick) {        intrEvent = new IntrEvent(this, intrEventTick, true);    }}voidDevice::serialize(std::ostream &os){    int count;    // Serialize the PciDev base class    Base::serialize(os);    if (rxState == rxCopy)        panic("can't serialize with an in flight dma request rxState=%s",              RxStateStrings[rxState]);    if (txState == txCopy)        panic("can't serialize with an in flight dma request txState=%s",              TxStateStrings[txState]);    /*     * Serialize the device registers     */    SERIALIZE_SCALAR(regs.Config);    SERIALIZE_SCALAR(regs.IntrStatus);    SERIALIZE_SCALAR(regs.IntrMask);    SERIALIZE_SCALAR(regs.RxMaxCopy);    SERIALIZE_SCALAR(regs.TxMaxCopy);    SERIALIZE_SCALAR(regs.RxMaxIntr);    SERIALIZE_SCALAR(regs.VirtualCount);    SERIALIZE_SCALAR(regs.RxData);    SERIALIZE_SCALAR(regs.RxDone);    SERIALIZE_SCALAR(regs.TxData);    SERIALIZE_SCALAR(regs.TxDone);    /*     * Serialize the virtual nic state     */    int virtualRegsSize = virtualRegs.size();    SERIALIZE_SCALAR(virtualRegsSize);    for (int i = 0; i < virtualRegsSize; ++i) {        VirtualReg *vnic = &virtualRegs[i];        std::string reg = csprintf("vnic%d", i);        paramOut(os, reg + ".RxData", vnic->RxData);        paramOut(os, reg + ".RxDone", vnic->RxDone);        paramOut(os, reg + ".TxData", vnic->TxData);        paramOut(os, reg + ".TxDone", vnic->TxDone);        bool rxPacketExists = vnic->rxPacket != rxFifo.end();        paramOut(os, reg + ".rxPacketExists", rxPacketExists);        if (rxPacketExists) {            int rxPacket = 0;            PacketFifo::iterator i = rxFifo.begin();            while (i != vnic->rxPacket) {                assert(i != rxFifo.end());                ++i;                ++rxPacket;            }            paramOut(os, reg + ".rxPacket", rxPacket);            paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);            paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);        }        paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);    }    int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);    SERIALIZE_SCALAR(rxFifoPtr);    SERIALIZE_SCALAR(rxActive);    VirtualList::iterator i, end;    for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)        paramOut(os, csprintf("rxList%d", count++), *i);    int rxListSize = count;    SERIALIZE_SCALAR(rxListSize);    for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)        paramOut(os, csprintf("rxBusy%d", count++), *i);    int rxBusySize = count;    SERIALIZE_SCALAR(rxBusySize);    for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)        paramOut(os, csprintf("txList%d", count++), *i);    int txListSize = count;    SERIALIZE_SCALAR(txListSize);    /*     * Serialize rx state machine     */    int rxState = this->rxState;    SERIALIZE_SCALAR(rxState);    SERIALIZE_SCALAR(rxEmpty);    SERIALIZE_SCALAR(rxLow);    rxFifo.serialize("rxFifo", os);    /*     * Serialize tx state machine     */    int txState = this->txState;    SERIALIZE_SCALAR(txState);    SERIALIZE_SCALAR(txFull);    txFifo.serialize("txFifo", os);    bool txPacketExists = txPacket;    SERIALIZE_SCALAR(txPacketExists);    if (txPacketExists) {        txPacket->serialize("txPacket", os);        SERIALIZE_SCALAR(txPacketOffset);        SERIALIZE_SCALAR(txPacketBytes);    }    /*     * If there's a pending transmit, store the time so we can     * reschedule it later     */    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;    SERIALIZE_SCALAR(transmitTick);}voidDevice::unserialize(Checkpoint *cp, const std::string &section){    // Unserialize the PciDev base class    Base::unserialize(cp, section);    /*     * Unserialize the device registers     */    UNSERIALIZE_SCALAR(regs.Config);    UNSERIALIZE_SCALAR(regs.IntrStatus);    UNSERIALIZE_SCALAR(regs.IntrMask);    UNSERIALIZE_SCALAR(regs.RxMaxCopy);    UNSERIALIZE_SCALAR(regs.TxMaxCopy);    UNSERIALIZE_SCALAR(regs.RxMaxIntr);    UNSERIALIZE_SCALAR(regs.VirtualCount);    UNSERIALIZE_SCALAR(regs.RxData);    UNSERIALIZE_SCALAR(regs.RxDone);    UNSERIALIZE_SCALAR(regs.TxData);    UNSERIALIZE_SCALAR(regs.TxDone);    UNSERIALIZE_SCALAR(rxActive);    int rxListSize;    UNSERIALIZE_SCALAR(rxListSize);    rxList.clear();    for (int i = 0; i < rxListSize; ++i) {        int value;        paramIn(cp, section, csprintf("rxList%d", i), value);        rxList.push_back(value);    }    int rxBusySize;    UNSERIALIZE_SCALAR(rxBusySize);    rxBusy.clear();    for (int i = 0; i < rxBusySize; ++i) {        int value;        paramIn(cp, section, csprintf("rxBusy%d", i), value);        rxBusy.push_back(value);    }    int txListSize;    UNSERIALIZE_SCALAR(txListSize);    txList.clear();    for (int i = 0; i < txListSize; ++i) {        int value;        paramIn(cp, section, csprintf("txList%d", i), value);        txList.push_back(value);    }    /*     * Unserialize rx state machine     */    int rxState;    UNSERIALIZE_SCALAR(rxState);    UNSERIALIZE_SCALAR(rxEmpty);    UNSERIALIZE_SCALAR(rxLow);    this->rxState = (RxState) rxState;    rxFifo.unserialize("rxFifo", cp, section);    int rxFifoPtr;    UNSERIALIZE_SCALAR(rxFifoPtr);    this->rxFifoPtr = rxFifo.begin();    for (int i = 0; i < rxFifoPtr; ++i)        ++this->rxFifoPtr;    /*     * Unserialize tx state machine     */    int txState;    UNSERIALIZE_SCALAR(txState);    UNSERIALIZE_SCALAR(txFull);    this->txState = (TxState) txState;    txFifo.unserialize("txFifo", cp, section);    bool txPacketExists;    UNSERIALIZE_SCALAR(txPacketExists);    txPacket = 0;    if (txPacketExists) {        txPacket = new EthPacketData(16384);        txPacket->unserialize("txPacket", cp, section);        UNSERIALIZE_SCALAR(txPacketOffset);        UNSERIALIZE_SCALAR(txPacketBytes);    }    /*     * unserialize the virtual nic registers/state     *     * this must be done after the unserialization of the rxFifo     * because the packet iterators depend on the fifo being populated     */    int virtualRegsSize;    UNSERIALIZE_SCALAR(virtualRegsSize);    virtualRegs.clear();    virtualRegs.resize(virtualRegsSize);    for (int i = 0; i < virtualRegsSize; ++i) {        VirtualReg *vnic = &virtualRegs[i];        std::string reg = csprintf("vnic%d", i);        paramIn(cp, section, reg + ".RxData", vnic->RxData);        paramIn(cp, section, reg + ".RxDone", vnic->RxDone);        paramIn(cp, section, reg + ".TxData", vnic->TxData);        paramIn(cp, section, reg + ".TxDone", vnic->TxDone);        vnic->rxUnique = rxUnique++;        vnic->txUnique = txUnique++;        bool rxPacketExists;        paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);        if (rxPacketExists) {            int rxPacket;            paramIn(cp, section, reg + ".rxPacket", rxPacket);            vnic->rxPacket = rxFifo.begin();            while (rxPacket--)                ++vnic->rxPacket;            paramIn(cp, section, reg + ".rxPacketOffset",                    vnic->rxPacketOffset);            paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);        } else {            vnic->rxPacket = rxFifo.end();        }        paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);    }    /*     * If there's a pending transmit, reschedule it now     */    Tick transmitTick;    UNSERIALIZE_SCALAR(transmitTick);    if (transmitTick)        txEvent.schedule(curTick + transmitTick);    pioPort->sendStatusChange(Port::RangeChange);}/* namespace Sinic */ }Sinic::Device *SinicParams::create(){    return new Sinic::Device(this);}

⌨️ 快捷键说明

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