SINIC: Commit old code from ASPLOS 2006 studies.
NOTE: This code was written by Nathan Binkert in 2006 and is properly copyright "The Regents of the University of Michigan"
This commit is contained in:
@@ -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")
|
||||
|
||||
226
src/dev/sinic.cc
226
src/dev/sinic.cc
@@ -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 §ion)
|
||||
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 §ion)
|
||||
|
||||
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 §ion)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); }
|
||||
uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); }
|
||||
uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(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
|
||||
|
||||
@@ -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" },
|
||||
{ 8, true, false, "RxDone" },
|
||||
invalid,
|
||||
{ 8, true, false, "RxWait" },
|
||||
{ 8, true, false, "RxWait" },
|
||||
invalid,
|
||||
{ 8, true, true, "TxData" },
|
||||
{ 8, true, true, "TxData" },
|
||||
invalid,
|
||||
{ 8, true, false, "TxDone" },
|
||||
{ 8, true, false, "TxDone" },
|
||||
invalid,
|
||||
{ 8, true, false, "TxWait" },
|
||||
{ 8, true, false, "TxWait" },
|
||||
invalid,
|
||||
{ 8, true, false, "HwAddr" },
|
||||
{ 8, true, false, "HwAddr" },
|
||||
invalid,
|
||||
{ 8, true, false, "RxStatus" },
|
||||
invalid,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user