SINIC: Commit old code from ASPLOS 2006 studies.
authorNathan Binkert <nate@binkert.org>
Thu, 9 Oct 2008 11:58:23 +0000 (04:58 -0700)
committerNathan Binkert <nate@binkert.org>
Thu, 9 Oct 2008 11:58:23 +0000 (04:58 -0700)
NOTE: This code was written by Nathan Binkert in 2006 and is properly copyright
"The Regents of the University of Michigan"

src/dev/Ethernet.py
src/dev/sinic.cc
src/dev/sinic.hh
src/dev/sinicreg.hh

index 01384b32bb71c7b3aa190f5fee17daf3c7c7677a..cf513b834a2f832d15b10518312139ebd19dfa9e 100644 (file)
@@ -171,6 +171,9 @@ class Sinic(EtherDevBase):
     tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold")
     tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold")
     virtual_count = Param.UInt32(1, "Virtualized SINIC")
+    zero_copy_size = Param.UInt32(64, "Bytes to copy if below threshold")
+    zero_copy_threshold = Param.UInt32(256,
+        "Only zero copy above this threshold")
     zero_copy = Param.Bool(False, "Zero copy receive")
     delay_copy = Param.Bool(False, "Delayed copy transmit")
     virtual_addr = Param.Bool(False, "Virtual addressing")
index e875a8bcce8b81b6abbe10150d91210f90851fa8..1fa8095d388449079af82d87de4ea95d97ae4732 100644 (file)
@@ -45,6 +45,7 @@
 #include "sim/host.hh"
 #include "sim/stats.hh"
 
+using namespace std;
 using namespace Net;
 using namespace TheISA;
 
@@ -265,6 +266,35 @@ Device::regStats()
     totPackets = txPackets + rxPackets;
     txPacketRate = txPackets / simSeconds;
     rxPacketRate = rxPackets / simSeconds;
+
+    _maxVnicDistance = 0;
+
+    maxVnicDistance
+        .name(name() + ".maxVnicDistance")
+        .desc("maximum vnic distance")
+        ;
+
+    totalVnicDistance
+        .name(name() + ".totalVnicDistance")
+        .desc("total vnic distance")
+        ;
+    numVnicDistance
+        .name(name() + ".numVnicDistance")
+        .desc("number of vnic distance measurements")
+        ;
+
+    avgVnicDistance
+        .name(name() + ".avgVnicDistance")
+        .desc("average vnic distance")
+        ;
+
+    avgVnicDistance = totalVnicDistance / numVnicDistance;
+}
+
+void
+Device::resetStats()
+{
+    _maxVnicDistance = 0;
 }
 
 EtherInt*
@@ -289,6 +319,10 @@ Device::prepareIO(int cpu, int index)
               index, size);
 }
 
+//add stats for head of line blocking
+//add stats for average fifo length
+//add stats for average number of vnics busy
+
 void
 Device::prepareRead(int cpu, int index)
 {
@@ -301,7 +335,7 @@ Device::prepareRead(int cpu, int index)
     uint64_t rxdone = vnic.RxDone;
     rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));
     rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());
-    rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark);
+    rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoHigh);
     rxdone = set_RxDone_NotHigh(rxdone, rxLow);
     regs.RxData = vnic.RxData;
     regs.RxDone = rxdone;
@@ -311,10 +345,23 @@ Device::prepareRead(int cpu, int index)
     uint64_t txdone = vnic.TxDone;
     txdone = set_TxDone_Packets(txdone, txFifo.packets());
     txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
-    txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);
+    txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoLow);
     regs.TxData = vnic.TxData;
     regs.TxDone = txdone;
     regs.TxWait = txdone;
+
+    int head = 0xffff;
+
+    if (!rxFifo.empty()) {
+        int vnic = rxFifo.begin()->priv;
+        if (vnic != -1 && virtualRegs[vnic].rxPacketOffset > 0)
+            head = vnic;
+    }
+
+    regs.RxStatus = set_RxStatus_Head(regs.RxStatus, head);
+    regs.RxStatus = set_RxStatus_Busy(regs.RxStatus, rxBusyCount);
+    regs.RxStatus = set_RxStatus_Mapped(regs.RxStatus, rxMappedCount);
+    regs.RxStatus = set_RxStatus_Dirty(regs.RxStatus, rxDirtyCount);
 }
 
 void
@@ -473,22 +520,25 @@ Device::write(PacketPtr pkt)
         vnic.rxUnique = rxUnique++;
         vnic.RxDone = Regs::RxDone_Busy;
         vnic.RxData = pkt->get<uint64_t>();
+        rxBusyCount++;
 
         if (Regs::get_RxData_Vaddr(pkt->get<uint64_t>())) {
             panic("vtophys not implemented in newmem");
-/*            Addr vaddr = Regs::get_RxData_Addr(reg64);
+#ifdef SINIC_VTOPHYS
+            Addr vaddr = Regs::get_RxData_Addr(reg64);
             Addr paddr = vtophys(req->xc, vaddr);
             DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "
                     "vaddr=%#x, paddr=%#x\n",
                     index, vnic.rxUnique, vaddr, paddr);
 
-            vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/
+            vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);
+#endif
         } else {
             DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
                     index, vnic.rxUnique);
         }
 
-        if (vnic.rxPacket == rxFifo.end()) {
+        if (vnic.rxIndex == rxFifo.end()) {
             DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
             rxList.push_back(index);
         } else {
@@ -512,15 +562,17 @@ Device::write(PacketPtr pkt)
 
         if (Regs::get_TxData_Vaddr(pkt->get<uint64_t>())) {
             panic("vtophys won't work here in newmem.\n");
-            /*Addr vaddr = Regs::get_TxData_Addr(reg64);
+#ifdef SINIC_VTOPHYS
+            Addr vaddr = Regs::get_TxData_Addr(reg64);
             Addr paddr = vtophys(req->xc, vaddr);
-            DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "
+            DPRINTF(EthernetPIO, "write TxData vnic %d (txunique %d): "
                     "vaddr=%#x, paddr=%#x\n",
                     index, vnic.txUnique, vaddr, paddr);
 
-            vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/
+            vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);
+#endif
         } else {
-            DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
+            DPRINTF(EthernetPIO, "write TxData vnic %d (txunique %d)\n",
                     index, vnic.txUnique);
         }
 
@@ -761,18 +813,31 @@ Device::reset()
     regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
     regs.RxMaxCopy = params()->rx_max_copy;
     regs.TxMaxCopy = params()->tx_max_copy;
-    regs.RxMaxIntr = params()->rx_max_intr;
+    regs.ZeroCopySize = params()->zero_copy_size;
+    regs.ZeroCopyMark = params()->zero_copy_threshold;
     regs.VirtualCount = params()->virtual_count;
+    regs.RxMaxIntr = params()->rx_max_intr;
     regs.RxFifoSize = params()->rx_fifo_size;
     regs.TxFifoSize = params()->tx_fifo_size;
-    regs.RxFifoMark = params()->rx_fifo_threshold;
-    regs.TxFifoMark = params()->tx_fifo_threshold;
+    regs.RxFifoLow = params()->rx_fifo_low_mark;
+    regs.TxFifoLow = params()->tx_fifo_threshold;
+    regs.RxFifoHigh = params()->rx_fifo_threshold;
+    regs.TxFifoHigh = params()->tx_fifo_high_mark;
     regs.HwAddr = params()->hardware_address;
 
+    if (regs.RxMaxCopy < regs.ZeroCopyMark)
+        panic("Must be able to copy at least as many bytes as the threshold");
+
+    if (regs.ZeroCopySize >= regs.ZeroCopyMark)
+        panic("The number of bytes to copy must be less than the threshold");
+
     rxList.clear();
     rxBusy.clear();
     rxActive = -1;
     txList.clear();
+    rxBusyCount = 0;
+    rxDirtyCount = 0;
+    rxMappedCount = 0;
 
     rxState = rxIdle;
     txState = txIdle;
@@ -788,7 +853,7 @@ Device::reset()
     virtualRegs.clear();
     virtualRegs.resize(size);
     for (int i = 0; i < size; ++i)
-        virtualRegs[i].rxPacket = rxFifo.end();
+        virtualRegs[i].rxIndex = rxFifo.end();
 }
 
 void
@@ -822,6 +887,7 @@ Device::rxKick()
     }
 
   next:
+    rxFifo.check();
     if (rxState == rxIdle)
         goto exit;
 
@@ -845,12 +911,28 @@ Device::rxKick()
             int size = virtualRegs.size();
             for (int i = 0; i < size; ++i) {
                 VirtualReg *vn = &virtualRegs[i];
-                if (vn->rxPacket != end &&
-                    !Regs::get_RxDone_Busy(vn->RxDone)) {
+                bool busy = Regs::get_RxDone_Busy(vn->RxDone);
+                if (vn->rxIndex != end) {
+                    bool dirty = vn->rxPacketOffset > 0;
+                    const char *status;
+
+                    if (busy && dirty)
+                        status = "busy,dirty";
+                    else if (busy)
+                        status = "busy";
+                    else if (dirty)
+                        status = "dirty";
+                    else
+                        status = "mapped";
+
                     DPRINTF(EthernetSM,
-                            "vnic %d (rxunique %d), has outstanding packet %d\n",
-                            i, vn->rxUnique,
-                            rxFifo.countPacketsBefore(vn->rxPacket));
+                            "vnic %d %s (rxunique %d), packet %d, slack %d\n",
+                            i, status, vn->rxUnique,
+                            rxFifo.countPacketsBefore(vn->rxIndex),
+                            vn->rxIndex->slack);
+                } else if (busy) {
+                    DPRINTF(EthernetSM, "vnic %d unmapped (rxunique %d)\n",
+                            i, vn->rxUnique);
                 }
             }
         }
@@ -860,7 +942,7 @@ Device::rxKick()
             rxBusy.pop_front();
             vnic = &virtualRegs[rxActive];
 
-            if (vnic->rxPacket == rxFifo.end())
+            if (vnic->rxIndex == rxFifo.end())
                 panic("continuing vnic without packet\n");
 
             DPRINTF(EthernetSM,
@@ -869,6 +951,14 @@ Device::rxKick()
 
             rxState = rxBeginCopy;
 
+            int vnic_distance = rxFifo.countPacketsBefore(vnic->rxIndex);
+            totalVnicDistance += vnic_distance;
+            numVnicDistance += 1;
+            if (vnic_distance > _maxVnicDistance) {
+                maxVnicDistance = vnic_distance;
+                _maxVnicDistance = vnic_distance;
+            }
+
             break;
         }
 
@@ -891,14 +981,16 @@ Device::rxKick()
                 rxActive, vnic->rxUnique);
 
         // Grab a new packet from the fifo.
-        vnic->rxPacket = rxFifoPtr++;
+        vnic->rxIndex = rxFifoPtr++;
+        vnic->rxIndex->priv = rxActive;
         vnic->rxPacketOffset = 0;
-        vnic->rxPacketBytes = vnic->rxPacket->packet->length;
+        vnic->rxPacketBytes = vnic->rxIndex->packet->length;
         assert(vnic->rxPacketBytes);
+        rxMappedCount++;
 
         vnic->rxDoneData = 0;
         /* scope for variables */ {
-            IpPtr ip(vnic->rxPacket->packet);
+            IpPtr ip(vnic->rxIndex->packet);
             if (ip) {
                 DPRINTF(Ethernet, "ID is %d\n", ip->id());
                 vnic->rxDoneData |= Regs::RxDone_IpPacket;
@@ -939,16 +1031,26 @@ Device::rxKick()
 
         rxDmaAddr = params()->platform->pciToDma(
                 Regs::get_RxData_Addr(vnic->RxData));
-        rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData),
+        rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData),
                             vnic->rxPacketBytes);
-        rxDmaData = vnic->rxPacket->packet->data + vnic->rxPacketOffset;
+
+        /*
+         * if we're doing zero/delay copy and we're below the fifo
+         * threshold, see if we should try to do the zero/defer copy
+         */
+        if ((Regs::get_Config_ZeroCopy(regs.Config) ||
+             Regs::get_Config_DelayCopy(regs.Config)) &&
+            !Regs::get_RxData_NoDelay(vnic->RxData) && rxLow) {
+            if (rxDmaLen > regs.ZeroCopyMark)
+                rxDmaLen = regs.ZeroCopySize;
+        }
+        rxDmaData = vnic->rxIndex->packet->data + vnic->rxPacketOffset;
         rxState = rxCopy;
         if (rxDmaAddr == 1LL) {
             rxState = rxCopyDone;
             break;
         }
 
-
         dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData);
         break;
 
@@ -959,17 +1061,25 @@ Device::rxKick()
       case rxCopyDone:
         vnic->RxDone = vnic->rxDoneData;
         vnic->RxDone |= Regs::RxDone_Complete;
+        rxBusyCount--;
 
         if (vnic->rxPacketBytes == rxDmaLen) {
+            if (vnic->rxPacketOffset)
+                rxDirtyCount--;
+
             // Packet is complete.  Indicate how many bytes were copied
             vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen);
 
             DPRINTF(EthernetSM,
                     "rxKick: packet complete on vnic %d (rxunique %d)\n",
                     rxActive, vnic->rxUnique);
-            rxFifo.remove(vnic->rxPacket);
-            vnic->rxPacket = rxFifo.end();
+            rxFifo.remove(vnic->rxIndex);
+            vnic->rxIndex = rxFifo.end();
+            rxMappedCount--;
         } else {
+            if (!vnic->rxPacketOffset)
+                rxDirtyCount++;
+
             vnic->rxPacketBytes -= rxDmaLen;
             vnic->rxPacketOffset += rxDmaLen;
             vnic->RxDone |= Regs::RxDone_More;
@@ -989,10 +1099,10 @@ Device::rxKick()
             rxEmpty = true;
         }
 
-        if (rxFifo.size() < params()->rx_fifo_low_mark)
+        if (rxFifo.size() < regs.RxFifoLow)
             rxLow = true;
 
-        if (rxFifo.size() > params()->rx_fifo_threshold)
+        if (rxFifo.size() > regs.RxFifoHigh)
             rxLow = false;
 
         devIntrPost(Regs::Intr_RxDMA);
@@ -1044,7 +1154,7 @@ Device::transmit()
     if (!interface->sendPacket(packet)) {
         DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
                 txFifo.avail());
-        goto reschedule;
+        return;
     }
 
     txFifo.pop();
@@ -1072,15 +1182,9 @@ Device::transmit()
             txFifo.avail());
 
     interrupts = Regs::Intr_TxPacket;
-    if (txFifo.size() < regs.TxFifoMark)
+    if (txFifo.size() < regs.TxFifoLow)
         interrupts |= Regs::Intr_TxLow;
     devIntrPost(interrupts);
-
-  reschedule:
-   if (!txFifo.empty() && !txEvent.scheduled()) {
-       DPRINTF(Ethernet, "reschedule transmit\n");
-       txEvent.schedule(curTick + retryTime);
-   }
 }
 
 void
@@ -1278,7 +1382,7 @@ Device::recvPacket(EthPacketPtr packet)
         return true;
     }
 
-    if (rxFifo.size() >= regs.RxFifoMark)
+    if (rxFifo.size() >= regs.RxFifoHigh)
         devIntrPost(Regs::Intr_RxHigh);
 
     if (!rxFifo.push(packet)) {
@@ -1372,19 +1476,13 @@ Device::serialize(std::ostream &os)
               TxStateStrings[txState]);
 
     /*
-     * Serialize the device registers
+     * Serialize the device registers that could be modified by the OS.
      */
     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
@@ -1400,12 +1498,12 @@ Device::serialize(std::ostream &os)
         paramOut(os, reg + ".TxData", vnic->TxData);
         paramOut(os, reg + ".TxDone", vnic->TxDone);
 
-        bool rxPacketExists = vnic->rxPacket != rxFifo.end();
+        bool rxPacketExists = vnic->rxIndex != rxFifo.end();
         paramOut(os, reg + ".rxPacketExists", rxPacketExists);
         if (rxPacketExists) {
             int rxPacket = 0;
             PacketFifo::iterator i = rxFifo.begin();
-            while (i != vnic->rxPacket) {
+            while (i != vnic->rxIndex) {
                 assert(i != rxFifo.end());
                 ++i;
                 ++rxPacket;
@@ -1418,10 +1516,15 @@ Device::serialize(std::ostream &os)
         paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
     }
 
-    int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
+    int rxFifoPtr = -1;
+    if (this->rxFifoPtr != rxFifo.end())
+        rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
     SERIALIZE_SCALAR(rxFifoPtr);
 
     SERIALIZE_SCALAR(rxActive);
+    SERIALIZE_SCALAR(rxBusyCount);
+    SERIALIZE_SCALAR(rxDirtyCount);
+    SERIALIZE_SCALAR(rxMappedCount);
 
     VirtualList::iterator i, end;
     for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
@@ -1478,21 +1581,18 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
     Base::unserialize(cp, section);
 
     /*
-     * Unserialize the device registers
+     * Unserialize the device registers that may have been written by the OS.
      */
     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);
+    UNSERIALIZE_SCALAR(rxBusyCount);
+    UNSERIALIZE_SCALAR(rxDirtyCount);
+    UNSERIALIZE_SCALAR(rxMappedCount);
 
     int rxListSize;
     UNSERIALIZE_SCALAR(rxListSize);
@@ -1533,9 +1633,13 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
 
     int rxFifoPtr;
     UNSERIALIZE_SCALAR(rxFifoPtr);
-    this->rxFifoPtr = rxFifo.begin();
-    for (int i = 0; i < rxFifoPtr; ++i)
-        ++this->rxFifoPtr;
+    if (rxFifoPtr >= 0) {
+        this->rxFifoPtr = rxFifo.begin();
+        for (int i = 0; i < rxFifoPtr; ++i)
+            ++this->rxFifoPtr;
+    } else {
+        this->rxFifoPtr = rxFifo.end();
+    }
 
     /*
      * Unserialize tx state machine
@@ -1582,15 +1686,15 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
         if (rxPacketExists) {
             int rxPacket;
             paramIn(cp, section, reg + ".rxPacket", rxPacket);
-            vnic->rxPacket = rxFifo.begin();
+            vnic->rxIndex = rxFifo.begin();
             while (rxPacket--)
-                ++vnic->rxPacket;
+                ++vnic->rxIndex;
 
             paramIn(cp, section, reg + ".rxPacketOffset",
                     vnic->rxPacketOffset);
             paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
         } else {
-            vnic->rxPacket = rxFifo.end();
+            vnic->rxIndex = rxFifo.end();
         }
         paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
     }
index e85d93fe471154ed8aaa6cc25fedd892f5ada9ed..3185e86963af5610006eba56df90ef84ebf5a512 100644 (file)
@@ -115,19 +115,24 @@ class Device : public Base
         uint32_t IntrMask;     // 0x0c
         uint32_t RxMaxCopy;    // 0x10
         uint32_t TxMaxCopy;    // 0x14
-        uint32_t RxMaxIntr;    // 0x18
-        uint32_t VirtualCount; // 0x1c
-        uint32_t RxFifoSize;   // 0x20
-        uint32_t TxFifoSize;   // 0x24
-        uint32_t RxFifoMark;   // 0x28
-        uint32_t TxFifoMark;   // 0x2c
-        uint64_t RxData;       // 0x30
-        uint64_t RxDone;       // 0x38
-        uint64_t RxWait;       // 0x40
-        uint64_t TxData;       // 0x48
-        uint64_t TxDone;       // 0x50
-        uint64_t TxWait;       // 0x58
-        uint64_t HwAddr;       // 0x60
+        uint32_t ZeroCopySize; // 0x18
+        uint32_t ZeroCopyMark; // 0x1c
+        uint32_t VirtualCount; // 0x20
+        uint32_t RxMaxIntr;    // 0x24
+        uint32_t RxFifoSize;   // 0x28
+        uint32_t TxFifoSize;   // 0x2c
+        uint32_t RxFifoLow;    // 0x30
+        uint32_t TxFifoLow;    // 0x34
+        uint32_t RxFifoHigh;   // 0x38
+        uint32_t TxFifoHigh;   // 0x3c
+        uint64_t RxData;       // 0x40
+        uint64_t RxDone;       // 0x48
+        uint64_t RxWait;       // 0x50
+        uint64_t TxData;       // 0x58
+        uint64_t TxDone;       // 0x60
+        uint64_t TxWait;       // 0x68
+        uint64_t HwAddr;       // 0x70
+        uint64_t RxStatus;     // 0x78
     } regs;
 
     struct VirtualReg {
@@ -136,7 +141,7 @@ class Device : public Base
         uint64_t TxData;
         uint64_t TxDone;
 
-        PacketFifo::iterator rxPacket;
+        PacketFifo::iterator rxIndex;
         int rxPacketOffset;
         int rxPacketBytes;
         uint64_t rxDoneData;
@@ -159,6 +164,10 @@ class Device : public Base
     int rxActive;
     VirtualList txList;
 
+    int rxBusyCount;
+    int rxMappedCount;
+    int rxDirtyCount;
+
     uint8_t  &regData8(Addr daddr) { return *((uint8_t *)&regs + daddr); }
     uint32_t &regData32(Addr daddr) { return *(uint32_t *)&regData8(daddr); }
     uint64_t &regData64(Addr daddr) { return *(uint64_t *)&regData8(daddr); }
@@ -300,8 +309,16 @@ class Device : public Base
     Stats::Scalar<> txTcpChecksums;
     Stats::Scalar<> txUdpChecksums;
 
+    Stats::Scalar<> totalVnicDistance;
+    Stats::Scalar<> numVnicDistance;
+    Stats::Scalar<> maxVnicDistance;
+    Stats::Formula avgVnicDistance;
+
+    int _maxVnicDistance;
+
   public:
     virtual void regStats();
+    virtual void resetStats();
 
 /**
  * Serialization stuff
index 791aabf6b074e5951327e3a3936c55da4c706d95..7ac7abad0ca5f8d104eea42a79a7f963f64329e2 100644 (file)
@@ -67,20 +67,25 @@ __SINIC_REG32(IntrStatus,    0x08); // 32: interrupt status
 __SINIC_REG32(IntrMask,      0x0c); // 32: interrupt mask
 __SINIC_REG32(RxMaxCopy,     0x10); // 32: max bytes per rx copy
 __SINIC_REG32(TxMaxCopy,     0x14); // 32: max bytes per tx copy
-__SINIC_REG32(RxMaxIntr,     0x18); // 32: max receives per interrupt
-__SINIC_REG32(VirtualCount,  0x1c); // 32: number of virutal NICs
-__SINIC_REG32(RxFifoSize,    0x20); // 32: rx fifo capacity in bytes
-__SINIC_REG32(TxFifoSize,    0x24); // 32: tx fifo capacity in bytes
-__SINIC_REG32(RxFifoMark,    0x28); // 32: rx fifo high watermark
-__SINIC_REG32(TxFifoMark,    0x2c); // 32: tx fifo low watermark
-__SINIC_REG32(RxData,        0x30); // 64: receive data
-__SINIC_REG32(RxDone,        0x38); // 64: receive done
-__SINIC_REG32(RxWait,        0x40); // 64: receive done (busy wait)
-__SINIC_REG32(TxData,        0x48); // 64: transmit data
-__SINIC_REG32(TxDone,        0x50); // 64: transmit done
-__SINIC_REG32(TxWait,        0x58); // 64: transmit done (busy wait)
-__SINIC_REG32(HwAddr,        0x60); // 64: mac address
-__SINIC_REG32(Size,          0x68); // register addres space size
+__SINIC_REG32(ZeroCopySize,  0x18); // 32: bytes to copy if below threshold
+__SINIC_REG32(ZeroCopyMark,  0x1c); // 32: only zero-copy above this threshold
+__SINIC_REG32(VirtualCount,  0x20); // 32: number of virutal NICs
+__SINIC_REG32(RxMaxIntr,     0x24); // 32: max receives per interrupt
+__SINIC_REG32(RxFifoSize,    0x28); // 32: rx fifo capacity in bytes
+__SINIC_REG32(TxFifoSize,    0x2c); // 32: tx fifo capacity in bytes
+__SINIC_REG32(RxFifoLow,     0x30); // 32: rx fifo low watermark
+__SINIC_REG32(TxFifoLow,     0x34); // 32: tx fifo low watermark
+__SINIC_REG32(RxFifoHigh,    0x38); // 32: rx fifo high watermark
+__SINIC_REG32(TxFifoHigh,    0x3c); // 32: tx fifo high watermark
+__SINIC_REG32(RxData,        0x40); // 64: receive data
+__SINIC_REG32(RxDone,        0x48); // 64: receive done
+__SINIC_REG32(RxWait,        0x50); // 64: receive done (busy wait)
+__SINIC_REG32(TxData,        0x58); // 64: transmit data
+__SINIC_REG32(TxDone,        0x60); // 64: transmit done
+__SINIC_REG32(TxWait,        0x68); // 64: transmit done (busy wait)
+__SINIC_REG32(HwAddr,        0x70); // 64: mac address
+__SINIC_REG32(RxStatus,      0x78);
+__SINIC_REG32(Size,          0x80); // register addres space size
 
 // Config register bits
 __SINIC_VAL32(Config_ZeroCopy, 12, 1); // enable zero copy
@@ -116,9 +121,10 @@ __SINIC_REG32(Intr_NoDelay,   0x01cc); // interrupts that aren't coalesced
 __SINIC_REG32(Intr_Res,      ~0x01ff); // reserved interrupt bits
 
 // RX Data Description
-__SINIC_VAL64(RxData_Vaddr, 60,  1); // Addr is virtual
-__SINIC_VAL64(RxData_Len,   40, 20); // 0 - 256k
-__SINIC_VAL64(RxData_Addr,   0, 40); // Address 1TB
+__SINIC_VAL64(RxData_NoDelay,  61,  1); // Don't Delay this copy
+__SINIC_VAL64(RxData_Vaddr,    60,  1); // Addr is virtual
+__SINIC_VAL64(RxData_Len,      40, 20); // 0 - 256k
+__SINIC_VAL64(RxData_Addr,      0, 40); // Address 1TB
 
 // TX Data Description
 __SINIC_VAL64(TxData_More,     63,  1); // Packet not complete (will dma more)
@@ -159,6 +165,11 @@ __SINIC_VAL64(TxDone_Res6,      21,  1); // reserved
 __SINIC_VAL64(TxDone_Res7,      20,  1); // reserved
 __SINIC_VAL64(TxDone_CopyLen,    0, 20); // up to 256k
 
+__SINIC_VAL64(RxStatus_Dirty,   48, 16);
+__SINIC_VAL64(RxStatus_Mapped,  32, 16);
+__SINIC_VAL64(RxStatus_Busy,    16, 16);
+__SINIC_VAL64(RxStatus_Head,     0, 16);
+
 struct Info
 {
     uint8_t size;
@@ -174,31 +185,37 @@ regInfo(Addr daddr)
 {
     static Regs::Info invalid = { 0, false, false, "invalid" };
     static Regs::Info info [] = {
-        { 4, true,  true,  "Config"     },
-        { 4, false, true,  "Command"    },
-        { 4, true,  true,  "IntrStatus" },
-        { 4, true,  true,  "IntrMask"   },
-        { 4, true,  false, "RxMaxCopy"  },
-        { 4, true,  false, "TxMaxCopy"  },
-        { 4, true,  false, "RxMaxIntr"  },
-        { 4, true,  false, "VirtualCount"  },
-        { 4, true,  false, "RxFifoSize" },
-        { 4, true,  false, "TxFifoSize" },
-        { 4, true,  false, "RxFifoMark" },
-        { 4, true,  false, "TxFifoMark" },
-        { 8, true,  true,  "RxData"     },
+        { 4, true,  true,  "Config"       },
+        { 4, false, true,  "Command"      },
+        { 4, true,  true,  "IntrStatus"   },
+        { 4, true,  true,  "IntrMask"     },
+        { 4, true,  false, "RxMaxCopy"    },
+        { 4, true,  false, "TxMaxCopy"    },
+        { 4, true,  false, "ZeroCopySize" },
+        { 4, true,  false, "ZeroCopyMark" },
+        { 4, true,  false, "VirtualCount" },
+        { 4, true,  false, "RxMaxIntr"    },
+        { 4, true,  false, "RxFifoSize"   },
+        { 4, true,  false, "TxFifoSize"   },
+        { 4, true,  false, "RxFifoLow"    },
+        { 4, true,  false, "TxFifoLow"    },
+        { 4, true,  false, "RxFifoHigh"   },
+        { 4, true,  false, "TxFifoHigh"   },
+        { 8, true,  true,  "RxData"       },
+        invalid,
+        { 8, true,  false, "RxDone"       },
         invalid,
-        { 8, true,  false, "RxDone"     },
+        { 8, true,  false, "RxWait"       },
         invalid,
-        { 8, true,  false, "RxWait"     },
+        { 8, true,  true,  "TxData"       },
         invalid,
-        { 8, true,  true,  "TxData"     },
+        { 8, true,  false, "TxDone"       },
         invalid,
-        { 8, true,  false, "TxDone"     },
+        { 8, true,  false, "TxWait"       },
         invalid,
-        { 8, true,  false, "TxWait"     },
+        { 8, true,  false, "HwAddr"       },
         invalid,
-        { 8, true,  false, "HwAddr"     },
+        { 8, true,  false, "RxStatus"     },
         invalid,
     };