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