Major update to sinic to support VSINIC better
dev/sinic.cc: - Size the virtualRegs array based on the configured value - Add debugging stuff for uniquely identifying vnic usage - Only count totally unprocessed packets when notifying via RxDone - Add initial virtual address support - Fix some bugs in accessing packets out of order to make sure that busy packets are processed first - Add fifo watermark stuff - Make number of vnics, zero/delay copy and watermarks parameters dev/sinic.hh: add rxUnique and txUnique to uniquely identify tx and rx VNICs Create a separate list of Busy VNICs since more than one might be busy and we want to service those first Add more watermark stuff and new parameters dev/sinicreg.hh: Make the number of virtual nics a read-only parameter add bits for ZeroCopy/DelayCopy rename Virtual to Vaddr so it's not ambiguous Add a flag for TxData/RxData to indicate a virtual address Report rxfifo status in RxDone python/m5/objects/Ethernet.py: add more options for the fifo thresholds add number of vnics as a parameter add copy type as a parameter add virtual addressing as a parameter --HG-- extra : convert_revision : 850e2433b585d65469d4c5d85ad7ca820db10f4a
This commit is contained in:
parent
225345e50e
commit
8e9d44477c
4 changed files with 234 additions and 49 deletions
231
dev/sinic.cc
231
dev/sinic.cc
|
@ -85,7 +85,8 @@ Base::Base(Params *p)
|
|||
}
|
||||
|
||||
Device::Device(Params *p)
|
||||
: Base(p), plat(p->plat), physmem(p->physmem),
|
||||
: Base(p), plat(p->plat), physmem(p->physmem), rxUnique(0), txUnique(0),
|
||||
virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
|
||||
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
|
||||
rxKickTick(0), txKickTick(0),
|
||||
txEvent(this), rxDmaEvent(this), txDmaEvent(this),
|
||||
|
@ -315,12 +316,9 @@ void
|
|||
Device::prepareIO(int cpu, int index)
|
||||
{
|
||||
int size = virtualRegs.size();
|
||||
if (index < size)
|
||||
return;
|
||||
|
||||
virtualRegs.resize(index + 1);
|
||||
for (int i = size; i <= index; ++i)
|
||||
virtualRegs[i].rxPacket = rxFifo.end();
|
||||
if (index > size)
|
||||
panic("Trying to access a vnic that doesn't exist %d > %d\n",
|
||||
index, size);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -333,7 +331,10 @@ Device::prepareRead(int cpu, int index)
|
|||
|
||||
// update rx registers
|
||||
uint64_t rxdone = vnic.RxDone;
|
||||
rxdone = set_RxDone_Packets(rxdone, rxFifo.packets());
|
||||
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_NotHigh(rxdone, rxLow);
|
||||
regs.RxData = vnic.RxData;
|
||||
regs.RxDone = rxdone;
|
||||
regs.RxWait = rxdone;
|
||||
|
@ -527,10 +528,32 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
|||
panic("receive machine busy with another request! rxState=%s",
|
||||
RxStateStrings[rxState]);
|
||||
|
||||
vnic.rxUnique = rxUnique++;
|
||||
vnic.RxDone = Regs::RxDone_Busy;
|
||||
vnic.RxData = reg64;
|
||||
|
||||
if (Regs::get_RxData_Vaddr(reg64)) {
|
||||
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);
|
||||
} else {
|
||||
DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
|
||||
index, vnic.rxUnique);
|
||||
}
|
||||
|
||||
if (vnic.rxPacket == rxFifo.end()) {
|
||||
DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
|
||||
rxList.push_back(index);
|
||||
if (rxEnable && rxState == rxIdle) {
|
||||
} else {
|
||||
DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");
|
||||
rxBusy.push_back(index);
|
||||
}
|
||||
|
||||
if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {
|
||||
rxState = rxFifoBlock;
|
||||
rxKick();
|
||||
}
|
||||
|
@ -541,8 +564,23 @@ Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
|||
panic("transmit machine busy with another request! txState=%s",
|
||||
TxStateStrings[txState]);
|
||||
|
||||
vnic.txUnique = txUnique++;
|
||||
vnic.TxDone = Regs::TxDone_Busy;
|
||||
vnic.TxData = reg64;
|
||||
|
||||
if (Regs::get_TxData_Vaddr(reg64)) {
|
||||
Addr vaddr = Regs::get_TxData_Addr(reg64);
|
||||
Addr paddr = vtophys(req->xc, vaddr);
|
||||
DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "
|
||||
"vaddr=%#x, paddr=%#x\n",
|
||||
index, vnic.txUnique, vaddr, paddr);
|
||||
|
||||
vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);
|
||||
} else {
|
||||
DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
|
||||
index, vnic.txUnique);
|
||||
}
|
||||
|
||||
if (txList.empty() || txList.front() != index)
|
||||
txList.push_back(index);
|
||||
if (txEnable && txState == txIdle && txList.front() == index) {
|
||||
|
@ -768,10 +806,21 @@ Device::reset()
|
|||
regs.Config |= Config_TxThread;
|
||||
if (params()->rss)
|
||||
regs.Config |= Config_RSS;
|
||||
if (params()->zero_copy)
|
||||
regs.Config |= Config_ZeroCopy;
|
||||
if (params()->delay_copy)
|
||||
regs.Config |= Config_DelayCopy;
|
||||
if (params()->virtual_addr)
|
||||
regs.Config |= Config_Vaddr;
|
||||
|
||||
if (params()->delay_copy && params()->zero_copy)
|
||||
panic("Can't delay copy and zero copy");
|
||||
|
||||
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.VirtualCount = params()->virtual_count;
|
||||
regs.RxFifoSize = params()->rx_fifo_size;
|
||||
regs.TxFifoSize = params()->tx_fifo_size;
|
||||
regs.RxFifoMark = params()->rx_fifo_threshold;
|
||||
|
@ -779,6 +828,8 @@ Device::reset()
|
|||
regs.HwAddr = params()->eaddr;
|
||||
|
||||
rxList.clear();
|
||||
rxBusy.clear();
|
||||
rxActive = -1;
|
||||
txList.clear();
|
||||
|
||||
rxState = rxIdle;
|
||||
|
@ -788,6 +839,7 @@ Device::reset()
|
|||
rxFifoPtr = rxFifo.end();
|
||||
txFifo.clear();
|
||||
rxEmpty = false;
|
||||
rxLow = true;
|
||||
txFull = false;
|
||||
|
||||
int size = virtualRegs.size();
|
||||
|
@ -825,7 +877,7 @@ Device::rxDmaDone()
|
|||
void
|
||||
Device::rxKick()
|
||||
{
|
||||
VirtualReg *vnic;
|
||||
VirtualReg *vnic = NULL;
|
||||
|
||||
DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n",
|
||||
RxStateStrings[rxState], rxFifo.size());
|
||||
|
@ -840,16 +892,50 @@ Device::rxKick()
|
|||
if (rxState == rxIdle)
|
||||
goto exit;
|
||||
|
||||
assert(!rxList.empty());
|
||||
vnic = &virtualRegs[rxList.front()];
|
||||
if (rxActive == -1) {
|
||||
if (rxState != rxFifoBlock)
|
||||
panic("no active vnic while in state %s", RxStateStrings[rxState]);
|
||||
|
||||
DPRINTF(EthernetSM, "processing rxState=%s for virtual nic %d\n",
|
||||
RxStateStrings[rxState], rxList.front());
|
||||
DPRINTF(EthernetSM, "processing rxState=%s\n",
|
||||
RxStateStrings[rxState]);
|
||||
} else {
|
||||
vnic = &virtualRegs[rxActive];
|
||||
DPRINTF(EthernetSM,
|
||||
"processing rxState=%s for vnic %d (rxunique %d)\n",
|
||||
RxStateStrings[rxState], rxActive, vnic->rxUnique);
|
||||
}
|
||||
|
||||
switch (rxState) {
|
||||
case rxFifoBlock:
|
||||
if (vnic->rxPacket != rxFifo.end()) {
|
||||
if (DTRACE(EthernetSM)) {
|
||||
PacketFifo::iterator end = rxFifo.end();
|
||||
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)) {
|
||||
DPRINTF(EthernetSM,
|
||||
"vnic %d (rxunique %d), has outstanding packet %d\n",
|
||||
i, vn->rxUnique,
|
||||
rxFifo.countPacketsBefore(vn->rxPacket));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rxBusy.empty()) {
|
||||
rxActive = rxBusy.front();
|
||||
rxBusy.pop_front();
|
||||
vnic = &virtualRegs[rxActive];
|
||||
|
||||
if (vnic->rxPacket == rxFifo.end())
|
||||
panic("continuing vnic without packet\n");
|
||||
|
||||
DPRINTF(EthernetSM,
|
||||
"continue processing for vnic %d (rxunique %d)\n",
|
||||
rxActive, vnic->rxUnique);
|
||||
|
||||
rxState = rxBeginCopy;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -858,8 +944,19 @@ Device::rxKick()
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (rxList.empty())
|
||||
panic("Not idle, but nothing to do!");
|
||||
|
||||
assert(!rxFifo.empty());
|
||||
|
||||
rxActive = rxList.front();
|
||||
rxList.pop_front();
|
||||
vnic = &virtualRegs[rxActive];
|
||||
|
||||
DPRINTF(EthernetSM,
|
||||
"processing new packet for vnic %d (rxunique %d)\n",
|
||||
rxActive, vnic->rxUnique);
|
||||
|
||||
// Grab a new packet from the fifo.
|
||||
vnic->rxPacket = rxFifoPtr++;
|
||||
vnic->rxPacketOffset = 0;
|
||||
|
@ -913,6 +1010,11 @@ Device::rxKick()
|
|||
rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
|
||||
rxState = rxCopy;
|
||||
|
||||
if (rxDmaAddr == 1LL) {
|
||||
rxState = rxCopyDone;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dmaInterface) {
|
||||
dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
|
||||
curTick, &rxDmaEvent, true);
|
||||
|
@ -934,31 +1036,44 @@ Device::rxKick()
|
|||
goto exit;
|
||||
|
||||
case rxCopyDone:
|
||||
vnic->RxDone = vnic->rxDoneData | rxDmaLen;
|
||||
vnic->RxDone = vnic->rxDoneData;
|
||||
vnic->RxDone |= Regs::RxDone_Complete;
|
||||
|
||||
if (vnic->rxPacketBytes == rxDmaLen) {
|
||||
DPRINTF(EthernetSM, "rxKick: packet complete on vnic %d\n",
|
||||
rxList.front());
|
||||
// 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();
|
||||
} else {
|
||||
vnic->RxDone |= Regs::RxDone_More;
|
||||
vnic->rxPacketBytes -= rxDmaLen;
|
||||
vnic->rxPacketOffset += rxDmaLen;
|
||||
vnic->RxDone |= Regs::RxDone_More;
|
||||
vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone,
|
||||
vnic->rxPacketBytes);
|
||||
DPRINTF(EthernetSM,
|
||||
"rxKick: packet not complete on vnic %d: %d bytes left\n",
|
||||
rxList.front(), vnic->rxPacketBytes);
|
||||
"rxKick: packet not complete on vnic %d (rxunique %d): "
|
||||
"%d bytes left\n",
|
||||
rxActive, vnic->rxUnique, vnic->rxPacketBytes);
|
||||
}
|
||||
|
||||
rxList.pop_front();
|
||||
rxState = rxList.empty() ? rxIdle : rxFifoBlock;
|
||||
rxActive = -1;
|
||||
rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock;
|
||||
|
||||
if (rxFifo.empty()) {
|
||||
devIntrPost(Regs::Intr_RxEmpty);
|
||||
rxEmpty = true;
|
||||
}
|
||||
|
||||
if (rxFifo.size() < params()->rx_fifo_low_mark)
|
||||
rxLow = true;
|
||||
|
||||
if (rxFifo.size() > params()->rx_fifo_threshold)
|
||||
rxLow = false;
|
||||
|
||||
devIntrPost(Regs::Intr_RxDMA);
|
||||
break;
|
||||
|
||||
|
@ -1353,6 +1468,7 @@ Device::serialize(ostream &os)
|
|||
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);
|
||||
|
@ -1372,8 +1488,6 @@ Device::serialize(ostream &os)
|
|||
paramOut(os, reg + ".TxData", vnic->TxData);
|
||||
paramOut(os, reg + ".TxDone", vnic->TxDone);
|
||||
|
||||
PacketFifo::iterator rxFifoPtr;
|
||||
|
||||
bool rxPacketExists = vnic->rxPacket != rxFifo.end();
|
||||
paramOut(os, reg + ".rxPacketExists", rxPacketExists);
|
||||
if (rxPacketExists) {
|
||||
|
@ -1392,18 +1506,26 @@ Device::serialize(ostream &os)
|
|||
paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
|
||||
}
|
||||
|
||||
VirtualList::iterator i, end;
|
||||
int count;
|
||||
int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
|
||||
SERIALIZE_SCALAR(rxFifoPtr);
|
||||
|
||||
int rxListSize = rxList.size();
|
||||
SERIALIZE_SCALAR(rxListSize);
|
||||
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);
|
||||
|
||||
int txListSize = txList.size();
|
||||
SERIALIZE_SCALAR(txListSize);
|
||||
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
|
||||
|
@ -1411,6 +1533,7 @@ Device::serialize(ostream &os)
|
|||
int rxState = this->rxState;
|
||||
SERIALIZE_SCALAR(rxState);
|
||||
SERIALIZE_SCALAR(rxEmpty);
|
||||
SERIALIZE_SCALAR(rxLow);
|
||||
rxFifo.serialize("rxFifo", os);
|
||||
|
||||
/*
|
||||
|
@ -1451,11 +1574,14 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
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();
|
||||
|
@ -1465,6 +1591,15 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
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();
|
||||
|
@ -1480,9 +1615,16 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
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
|
||||
*/
|
||||
|
@ -1520,6 +1662,9 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
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) {
|
||||
|
@ -1549,10 +1694,8 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
/*
|
||||
* re-add addrRanges to bus bridges
|
||||
*/
|
||||
if (pioInterface) {
|
||||
if (pioInterface)
|
||||
pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
|
||||
pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
|
||||
}
|
||||
}
|
||||
|
||||
Tick
|
||||
|
@ -1634,6 +1777,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
|
|||
Param<uint32_t> rx_fifo_size;
|
||||
Param<uint32_t> tx_fifo_size;
|
||||
Param<uint32_t> rx_fifo_threshold;
|
||||
Param<uint32_t> rx_fifo_low_mark;
|
||||
Param<uint32_t> tx_fifo_high_mark;
|
||||
Param<uint32_t> tx_fifo_threshold;
|
||||
|
||||
Param<bool> rx_filter;
|
||||
|
@ -1641,6 +1786,10 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
|
|||
Param<bool> rx_thread;
|
||||
Param<bool> tx_thread;
|
||||
Param<bool> rss;
|
||||
Param<uint32_t> virtual_count;
|
||||
Param<bool> zero_copy;
|
||||
Param<bool> delay_copy;
|
||||
Param<bool> virtual_addr;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
|
@ -1678,13 +1827,19 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
|
|||
INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
|
||||
INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
|
||||
INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
|
||||
INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"),
|
||||
INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"),
|
||||
INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
|
||||
|
||||
INIT_PARAM(rx_filter, "Enable Receive Filter"),
|
||||
INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
|
||||
INIT_PARAM(rx_thread, ""),
|
||||
INIT_PARAM(tx_thread, ""),
|
||||
INIT_PARAM(rss, "")
|
||||
INIT_PARAM(rss, ""),
|
||||
INIT_PARAM(virtual_count, ""),
|
||||
INIT_PARAM(zero_copy, ""),
|
||||
INIT_PARAM(delay_copy, ""),
|
||||
INIT_PARAM(virtual_addr, "")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
|
@ -1726,6 +1881,8 @@ CREATE_SIM_OBJECT(Device)
|
|||
params->rx_fifo_size = rx_fifo_size;
|
||||
params->tx_fifo_size = tx_fifo_size;
|
||||
params->rx_fifo_threshold = rx_fifo_threshold;
|
||||
params->rx_fifo_low_mark = rx_fifo_low_mark;
|
||||
params->tx_fifo_high_mark = tx_fifo_high_mark;
|
||||
params->tx_fifo_threshold = tx_fifo_threshold;
|
||||
|
||||
params->rx_filter = rx_filter;
|
||||
|
@ -1733,6 +1890,10 @@ CREATE_SIM_OBJECT(Device)
|
|||
params->rx_thread = rx_thread;
|
||||
params->tx_thread = tx_thread;
|
||||
params->rss = rss;
|
||||
params->virtual_count = virtual_count;
|
||||
params->zero_copy = zero_copy;
|
||||
params->delay_copy = delay_copy;
|
||||
params->virtual_addr = virtual_addr;
|
||||
|
||||
return new Device(params);
|
||||
}
|
||||
|
|
16
dev/sinic.hh
16
dev/sinic.hh
|
@ -122,7 +122,7 @@ class Device : public Base
|
|||
uint32_t RxMaxCopy; // 0x10
|
||||
uint32_t TxMaxCopy; // 0x14
|
||||
uint32_t RxMaxIntr; // 0x18
|
||||
uint32_t Reserved0; // 0x1c
|
||||
uint32_t VirtualCount; // 0x1c
|
||||
uint32_t RxFifoSize; // 0x20
|
||||
uint32_t TxFifoSize; // 0x24
|
||||
uint32_t RxFifoMark; // 0x28
|
||||
|
@ -147,6 +147,9 @@ class Device : public Base
|
|||
int rxPacketBytes;
|
||||
uint64_t rxDoneData;
|
||||
|
||||
Counter rxUnique;
|
||||
Counter txUnique;
|
||||
|
||||
VirtualReg()
|
||||
: RxData(0), RxDone(0), TxData(0), TxDone(0),
|
||||
rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0)
|
||||
|
@ -154,8 +157,12 @@ class Device : public Base
|
|||
};
|
||||
typedef std::vector<VirtualReg> VirtualRegs;
|
||||
typedef std::list<int> VirtualList;
|
||||
Counter rxUnique;
|
||||
Counter txUnique;
|
||||
VirtualRegs virtualRegs;
|
||||
VirtualList rxList;
|
||||
VirtualList rxBusy;
|
||||
int rxActive;
|
||||
VirtualList txList;
|
||||
|
||||
uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); }
|
||||
|
@ -171,6 +178,7 @@ class Device : public Base
|
|||
PacketFifo rxFifo;
|
||||
PacketFifo::iterator rxFifoPtr;
|
||||
bool rxEmpty;
|
||||
bool rxLow;
|
||||
Addr rxDmaAddr;
|
||||
uint8_t *rxDmaData;
|
||||
int rxDmaLen;
|
||||
|
@ -347,6 +355,8 @@ class Device : public Base
|
|||
uint32_t rx_fifo_size;
|
||||
uint32_t tx_fifo_size;
|
||||
uint32_t rx_fifo_threshold;
|
||||
uint32_t rx_fifo_low_mark;
|
||||
uint32_t tx_fifo_high_mark;
|
||||
uint32_t tx_fifo_threshold;
|
||||
Tick dma_read_delay;
|
||||
Tick dma_read_factor;
|
||||
|
@ -356,6 +366,10 @@ class Device : public Base
|
|||
bool rx_thread;
|
||||
bool tx_thread;
|
||||
bool rss;
|
||||
uint32_t virtual_count;
|
||||
bool zero_copy;
|
||||
bool delay_copy;
|
||||
bool virtual_addr;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -55,8 +55,8 @@
|
|||
namespace Sinic {
|
||||
namespace Regs {
|
||||
|
||||
static const int VirtualMask = 0xff;
|
||||
static const int VirtualShift = 8;
|
||||
static const int VirtualMask = 0xff;
|
||||
|
||||
// Registers
|
||||
__SINIC_REG32(Config, 0x00); // 32: configuration register
|
||||
|
@ -66,7 +66,7 @@ __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(Reserved0, 0x1c); // 32: reserved
|
||||
__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
|
||||
|
@ -81,12 +81,14 @@ __SINIC_REG32(HwAddr, 0x60); // 64: mac address
|
|||
__SINIC_REG32(Size, 0x68); // register addres space size
|
||||
|
||||
// Config register bits
|
||||
__SINIC_VAL32(Config_ZeroCopy, 12, 1); // enable zero copy
|
||||
__SINIC_VAL32(Config_DelayCopy,11, 1); // enable delayed copy
|
||||
__SINIC_VAL32(Config_RSS, 10, 1); // enable receive side scaling
|
||||
__SINIC_VAL32(Config_RxThread, 9, 1); // enable receive threads
|
||||
__SINIC_VAL32(Config_TxThread, 8, 1); // enable transmit thread
|
||||
__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
|
||||
__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging
|
||||
__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing
|
||||
__SINIC_VAL32(Config_Vaddr, 5, 1); // enable virtual addressing
|
||||
__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors
|
||||
__SINIC_VAL32(Config_Poll, 3, 1); // enable polling
|
||||
__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts
|
||||
|
@ -112,13 +114,15 @@ __SINIC_REG32(Intr_NoDelay, 0x01cc); // interrupts that aren't coalesced
|
|||
__SINIC_REG32(Intr_Res, ~0x01ff); // reserved interrupt bits
|
||||
|
||||
// RX Data Description
|
||||
__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M
|
||||
__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)
|
||||
__SINIC_VAL64(TxData_Checksum, 62, 1); // do checksum
|
||||
__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M
|
||||
__SINIC_VAL64(TxData_Vaddr, 60, 1); // Addr is virtual
|
||||
__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 256k
|
||||
__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB
|
||||
|
||||
// RX Done/Busy Information
|
||||
|
@ -126,9 +130,9 @@ __SINIC_VAL64(RxDone_Packets, 32, 16); // number of packets in rx fifo
|
|||
__SINIC_VAL64(RxDone_Busy, 31, 1); // receive dma busy copying
|
||||
__SINIC_VAL64(RxDone_Complete, 30, 1); // valid data (packet complete)
|
||||
__SINIC_VAL64(RxDone_More, 29, 1); // Packet has more data (dma again)
|
||||
__SINIC_VAL64(RxDone_Res0, 28, 1); // reserved
|
||||
__SINIC_VAL64(RxDone_Res1, 27, 1); // reserved
|
||||
__SINIC_VAL64(RxDone_Res2, 26, 1); // reserved
|
||||
__SINIC_VAL64(RxDone_Empty, 28, 1); // rx fifo is empty
|
||||
__SINIC_VAL64(RxDone_High, 27, 1); // rx fifo is above the watermark
|
||||
__SINIC_VAL64(RxDone_NotHigh, 26, 1); // rxfifo never hit the high watermark
|
||||
__SINIC_VAL64(RxDone_TcpError, 25, 1); // TCP packet error (bad checksum)
|
||||
__SINIC_VAL64(RxDone_UdpError, 24, 1); // UDP packet error (bad checksum)
|
||||
__SINIC_VAL64(RxDone_IpError, 23, 1); // IP packet error (bad checksum)
|
||||
|
@ -175,7 +179,7 @@ regInfo(Addr daddr)
|
|||
{ 4, true, false, "RxMaxCopy" },
|
||||
{ 4, true, false, "TxMaxCopy" },
|
||||
{ 4, true, false, "RxMaxIntr" },
|
||||
invalid,
|
||||
{ 4, true, false, "VirtualCount" },
|
||||
{ 4, true, false, "RxFifoSize" },
|
||||
{ 4, true, false, "TxFifoSize" },
|
||||
{ 4, true, false, "RxFifoMark" },
|
||||
|
|
|
@ -105,8 +105,14 @@ class Sinic(EtherDevBase):
|
|||
rx_max_copy = Param.MemorySize('1514B', "rx max copy")
|
||||
tx_max_copy = Param.MemorySize('16kB', "tx max copy")
|
||||
rx_max_intr = Param.UInt32(10, "max rx packets per interrupt")
|
||||
rx_fifo_threshold = Param.MemorySize('48kB', "rx fifo high threshold")
|
||||
tx_fifo_threshold = Param.MemorySize('16kB', "tx fifo low threshold")
|
||||
rx_fifo_threshold = Param.MemorySize('384kB', "rx fifo high threshold")
|
||||
rx_fifo_low_mark = Param.MemorySize('128kB', "rx fifo low threshold")
|
||||
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 = Param.Bool(False, "Zero copy receive")
|
||||
delay_copy = Param.Bool(False, "Delayed copy transmit")
|
||||
virtual_addr = Param.Bool(False, "Virtual addressing")
|
||||
|
||||
class SinicInt(EtherInt):
|
||||
type = 'SinicInt'
|
||||
|
|
Loading…
Reference in a new issue