CPA: Add annotations to IGbE and CopyEngine device models.
This commit is contained in:
parent
d447ccb2c6
commit
bebbc9dc89
4 changed files with 227 additions and 5 deletions
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/cp_annotate.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "dev/copy_engine.hh"
|
||||
#include "mem/packet.hh"
|
||||
|
@ -427,6 +428,8 @@ CopyEngine::regStats()
|
|||
void
|
||||
CopyEngine::CopyEngineChannel::fetchDescriptor(Addr address)
|
||||
{
|
||||
anDq();
|
||||
anBegin("FetchDescriptor");
|
||||
DPRINTF(DMACopyEngine, "Reading descriptor from at memory location %#x(%#x)\n",
|
||||
address, ce->platform->pciToDma(address));
|
||||
assert(address);
|
||||
|
@ -455,6 +458,8 @@ CopyEngine::CopyEngineChannel::fetchDescComplete()
|
|||
if (inDrain()) return;
|
||||
writeCompletionStatus();
|
||||
} else {
|
||||
anBegin("Idle");
|
||||
anWait();
|
||||
busy = false;
|
||||
nextState = Idle;
|
||||
inDrain();
|
||||
|
@ -473,6 +478,7 @@ CopyEngine::CopyEngineChannel::fetchDescComplete()
|
|||
void
|
||||
CopyEngine::CopyEngineChannel::readCopyBytes()
|
||||
{
|
||||
anBegin("ReadCopyBytes");
|
||||
DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n",
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->src));
|
||||
|
@ -493,6 +499,7 @@ CopyEngine::CopyEngineChannel::readCopyBytesComplete()
|
|||
void
|
||||
CopyEngine::CopyEngineChannel::writeCopyBytes()
|
||||
{
|
||||
anBegin("WriteCopyBytes");
|
||||
DPRINTF(DMACopyEngine, "Writing %d bytes from buffer to memory location %#x(%#x)\n",
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->dest));
|
||||
|
@ -513,6 +520,8 @@ CopyEngine::CopyEngineChannel::writeCopyBytesComplete()
|
|||
cr.status.compl_desc_addr(lastDescriptorAddr >> 6);
|
||||
completionDataReg = cr.status() | 1;
|
||||
|
||||
anQ("DMAUsedDescQ", channelId, 1);
|
||||
anQ("AppRecvQ", curDmaDesc->user1, curDmaDesc->len);
|
||||
if (curDmaDesc->command & DESC_CTRL_CP_STS) {
|
||||
nextState = CompletionWrite;
|
||||
if (inDrain()) return;
|
||||
|
@ -529,6 +538,8 @@ CopyEngine::CopyEngineChannel::continueProcessing()
|
|||
busy = false;
|
||||
|
||||
if (underReset) {
|
||||
anBegin("Reset");
|
||||
anWait();
|
||||
underReset = false;
|
||||
refreshNext = false;
|
||||
busy = false;
|
||||
|
@ -549,12 +560,15 @@ CopyEngine::CopyEngineChannel::continueProcessing()
|
|||
} else {
|
||||
inDrain();
|
||||
nextState = Idle;
|
||||
anWait();
|
||||
anBegin("Idle");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CopyEngine::CopyEngineChannel::writeCompletionStatus()
|
||||
{
|
||||
anBegin("WriteCompletionStatus");
|
||||
DPRINTF(DMACopyEngine, "Writing completion status %#x to address %#x(%#x)\n",
|
||||
completionDataReg, cr.completionAddr,
|
||||
ce->platform->pciToDma(cr.completionAddr));
|
||||
|
@ -574,6 +588,7 @@ CopyEngine::CopyEngineChannel::writeStatusComplete()
|
|||
void
|
||||
CopyEngine::CopyEngineChannel::fetchNextAddr(Addr address)
|
||||
{
|
||||
anBegin("FetchNextAddr");
|
||||
DPRINTF(DMACopyEngine, "Fetching next address...\n");
|
||||
busy = true;
|
||||
cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address +
|
||||
|
@ -590,6 +605,8 @@ CopyEngine::CopyEngineChannel::fetchAddrComplete()
|
|||
DPRINTF(DMACopyEngine, "Got NULL descriptor, nothing more to do\n");
|
||||
busy = false;
|
||||
nextState = Idle;
|
||||
anWait();
|
||||
anBegin("Idle");
|
||||
inDrain();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -130,6 +130,36 @@ class CopyEngine : public PciDev
|
|||
void recvCommand();
|
||||
bool inDrain();
|
||||
void restartStateMachine();
|
||||
inline void anBegin(const char *s)
|
||||
{
|
||||
CPA::cpa()->hwBegin(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", s);
|
||||
}
|
||||
|
||||
inline void anWait()
|
||||
{
|
||||
CPA::cpa()->hwWe(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anDq()
|
||||
{
|
||||
CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anPq()
|
||||
{
|
||||
CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys,
|
||||
channelId, "CopyEngine", "DMAUnusedDescQ", channelId);
|
||||
}
|
||||
|
||||
inline void anQ(const char * s, uint64_t id, int size = 1)
|
||||
{
|
||||
CPA::cpa()->hwQ(CPA::FL_NONE, ce->sys, channelId,
|
||||
"CopyEngine", s, id, NULL, size);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -113,10 +113,20 @@ IGbE::IGbE(const Params *p)
|
|||
// Magic happy checksum value
|
||||
flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum));
|
||||
|
||||
// Store the MAC address as queue ID
|
||||
macAddr = p->hardware_address;
|
||||
|
||||
rxFifo.clear();
|
||||
txFifo.clear();
|
||||
}
|
||||
|
||||
void
|
||||
IGbE::init()
|
||||
{
|
||||
cpa = CPA::cpa();
|
||||
PciDev::init();
|
||||
}
|
||||
|
||||
EtherInt*
|
||||
IGbE::getEthPort(const std::string &if_name, int idx)
|
||||
{
|
||||
|
@ -793,6 +803,13 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s)
|
|||
pktEvent(this), pktHdrEvent(this), pktDataEvent(this)
|
||||
|
||||
{
|
||||
annSmFetch = "RX Desc Fetch";
|
||||
annSmWb = "RX Desc Writeback";
|
||||
annUnusedDescQ = "RX Unused Descriptors";
|
||||
annUnusedCacheQ = "RX Unused Descriptor Cache";
|
||||
annUsedCacheQ = "RX Used Descriptor Cache";
|
||||
annUsedDescQ = "RX Used Descriptors";
|
||||
annDescQ = "RX Descriptors";
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -910,6 +927,8 @@ IGbE::RxDescCache::pktComplete()
|
|||
RxDesc *desc;
|
||||
desc = unusedCache.front();
|
||||
|
||||
igbe->anBegin("RXS", "Update Desc");
|
||||
|
||||
uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ;
|
||||
DPRINTF(EthernetDesc, "pktPtr->length: %d bytesCopied: %d stripcrc offset: %d value written: %d %d\n",
|
||||
pktPtr->length, bytesCopied, crcfixup,
|
||||
|
@ -1052,8 +1071,11 @@ IGbE::RxDescCache::pktComplete()
|
|||
enableSm();
|
||||
pktDone = true;
|
||||
|
||||
igbe->anBegin("RXS", "Done Updating Desc");
|
||||
DPRINTF(EthernetDesc, "Processing of this descriptor complete\n");
|
||||
igbe->anDq("RXS", annUnusedCacheQ);
|
||||
unusedCache.pop_front();
|
||||
igbe->anQ("RXS", annUsedCacheQ);
|
||||
usedCache.push_back(desc);
|
||||
}
|
||||
|
||||
|
@ -1112,6 +1134,13 @@ IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
|
|||
useTso(false), pktEvent(this), headerEvent(this), nullEvent(this)
|
||||
|
||||
{
|
||||
annSmFetch = "TX Desc Fetch";
|
||||
annSmWb = "TX Desc Writeback";
|
||||
annUnusedDescQ = "TX Unused Descriptors";
|
||||
annUnusedCacheQ = "TX Unused Descriptor Cache";
|
||||
annUsedCacheQ = "TX Used Descriptor Cache";
|
||||
annUsedDescQ = "TX Used Descriptors";
|
||||
annDescQ = "TX Descriptors";
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1154,7 +1183,9 @@ IGbE::TxDescCache::processContextDesc()
|
|||
|
||||
TxdOp::setDd(desc);
|
||||
unusedCache.pop_front();
|
||||
igbe->anDq("TXS", annUnusedCacheQ);
|
||||
usedCache.push_back(desc);
|
||||
igbe->anQ("TXS", annUsedCacheQ);
|
||||
}
|
||||
|
||||
if (!unusedCache.size())
|
||||
|
@ -1298,6 +1329,8 @@ IGbE::TxDescCache::pktComplete()
|
|||
assert(unusedCache.size());
|
||||
assert(pktPtr);
|
||||
|
||||
igbe->anBegin("TXS", "Update Desc");
|
||||
|
||||
DPRINTF(EthernetDesc, "DMA of packet complete\n");
|
||||
|
||||
|
||||
|
@ -1323,7 +1356,9 @@ IGbE::TxDescCache::pktComplete()
|
|||
(pktPtr->length < ( tsoMss + tsoHeaderLen) &&
|
||||
tsoTotalLen != tsoUsedLen && useTso)) {
|
||||
assert(!useTso || (tsoDescBytesUsed == TxdOp::getLen(desc)));
|
||||
igbe->anDq("TXS", annUnusedCacheQ);
|
||||
unusedCache.pop_front();
|
||||
igbe->anQ("TXS", annUsedCacheQ);
|
||||
usedCache.push_back(desc);
|
||||
|
||||
tsoDescBytesUsed = 0;
|
||||
|
@ -1441,7 +1476,9 @@ IGbE::TxDescCache::pktComplete()
|
|||
|
||||
if (!useTso || TxdOp::getLen(desc) == tsoDescBytesUsed) {
|
||||
DPRINTF(EthernetDesc, "Descriptor Done\n");
|
||||
igbe->anDq("TXS", annUnusedCacheQ);
|
||||
unusedCache.pop_front();
|
||||
igbe->anQ("TXS", annUsedCacheQ);
|
||||
usedCache.push_back(desc);
|
||||
tsoDescBytesUsed = 0;
|
||||
}
|
||||
|
@ -1458,14 +1495,17 @@ IGbE::TxDescCache::pktComplete()
|
|||
tsoPktHasHeader = false;
|
||||
|
||||
if (igbe->regs.txdctl.wthresh() == 0) {
|
||||
igbe->anBegin("TXS", "Desc Writeback");
|
||||
DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
|
||||
writeback(0);
|
||||
} else if (igbe->regs.txdctl.gran() && igbe->regs.txdctl.wthresh() >=
|
||||
descInBlock(usedCache.size())) {
|
||||
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
|
||||
igbe->anBegin("TXS", "Desc Writeback");
|
||||
writeback((igbe->cacheBlockSize()-1)>>4);
|
||||
} else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
|
||||
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
|
||||
igbe->anBegin("TXS", "Desc Writeback");
|
||||
writeback((igbe->cacheBlockSize()-1)>>4);
|
||||
}
|
||||
|
||||
|
@ -1604,6 +1644,7 @@ IGbE::drain(Event *de)
|
|||
else
|
||||
changeState(Drained);
|
||||
|
||||
DPRINTF(EthernetSM, "got drain() returning %d", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -1617,6 +1658,7 @@ IGbE::resume()
|
|||
rxTick = true;
|
||||
|
||||
restartClock();
|
||||
DPRINTF(EthernetSM, "resuming from drain");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1625,6 +1667,7 @@ IGbE::checkDrain()
|
|||
if (!drainEvent)
|
||||
return;
|
||||
|
||||
DPRINTF(EthernetSM, "checkDrain() in drain\n");
|
||||
txFifoTick = false;
|
||||
txTick = false;
|
||||
rxTick = false;
|
||||
|
@ -1651,11 +1694,13 @@ IGbE::txStateMachine()
|
|||
&& !txDescCache.packetMultiDesc() && txPacket->length) {
|
||||
bool success;
|
||||
|
||||
anQ("TXS", "TX FIFO Q");
|
||||
DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
|
||||
success = txFifo.push(txPacket);
|
||||
txFifoTick = true && !drainEvent;
|
||||
assert(success);
|
||||
txPacket = NULL;
|
||||
anBegin("TXS", "Desc Writeback");
|
||||
txDescCache.writeback((cacheBlockSize()-1)>>4);
|
||||
return;
|
||||
}
|
||||
|
@ -1673,7 +1718,10 @@ IGbE::txStateMachine()
|
|||
if (!txDescCache.packetWaiting()) {
|
||||
if (txDescCache.descLeft() == 0) {
|
||||
postInterrupt(IT_TXQE);
|
||||
anBegin("TXS", "Desc Writeback");
|
||||
txDescCache.writeback(0);
|
||||
anBegin("TXS", "Desc Fetch");
|
||||
anWe("TXS", txDescCache.annUnusedCacheQ);
|
||||
txDescCache.fetchDescriptors();
|
||||
DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing "
|
||||
"writeback stopping ticking and posting TXQE\n");
|
||||
|
@ -1683,11 +1731,14 @@ IGbE::txStateMachine()
|
|||
|
||||
|
||||
if (!(txDescCache.descUnused())) {
|
||||
anBegin("TXS", "Desc Fetch");
|
||||
txDescCache.fetchDescriptors();
|
||||
anWe("TXS", txDescCache.annUnusedCacheQ);
|
||||
DPRINTF(EthernetSM, "TXS: No descriptors available in cache, fetching and stopping ticking\n");
|
||||
txTick = false;
|
||||
return;
|
||||
}
|
||||
anPq("TXS", txDescCache.annUnusedCacheQ);
|
||||
|
||||
|
||||
txDescCache.processContextDesc();
|
||||
|
@ -1700,6 +1751,8 @@ IGbE::txStateMachine()
|
|||
int size;
|
||||
size = txDescCache.getPacketSize(txPacket);
|
||||
if (size > 0 && txFifo.avail() > size) {
|
||||
anRq("TXS", "TX FIFO Q");
|
||||
anBegin("TXS", "DMA Packet");
|
||||
DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining "
|
||||
"DMA of next packet\n", size);
|
||||
txFifo.reserve(size);
|
||||
|
@ -1707,8 +1760,10 @@ IGbE::txStateMachine()
|
|||
} else if (size <= 0) {
|
||||
DPRINTF(EthernetSM, "TXS: getPacketSize returned: %d\n", size);
|
||||
DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");
|
||||
anBegin("TXS", "Desc Writeback");
|
||||
txDescCache.writeback(0);
|
||||
} else {
|
||||
anWf("TXS", "TX FIFO Q");
|
||||
DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "
|
||||
"available in FIFO\n");
|
||||
txTick = false;
|
||||
|
@ -1728,9 +1783,12 @@ IGbE::ethRxPkt(EthPacketPtr pkt)
|
|||
rxPackets++;
|
||||
|
||||
DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n");
|
||||
anBegin("RXQ", "Wire Recv");
|
||||
|
||||
|
||||
if (!regs.rctl.en()) {
|
||||
DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n");
|
||||
anBegin("RXQ", "FIFO Drop", CPA::FL_BAD);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1744,9 +1802,23 @@ IGbE::ethRxPkt(EthPacketPtr pkt)
|
|||
if (!rxFifo.push(pkt)) {
|
||||
DPRINTF(Ethernet, "RxFIFO: Packet won't fit in fifo... dropped\n");
|
||||
postInterrupt(IT_RXO, true);
|
||||
anBegin("RXQ", "FIFO Drop", CPA::FL_BAD);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CPA::available() && cpa->enabled()) {
|
||||
assert(sys->numSystemsRunning <= 2);
|
||||
System *other_sys;
|
||||
if (sys->systemList[0] == sys)
|
||||
other_sys = sys->systemList[1];
|
||||
else
|
||||
other_sys = sys->systemList[0];
|
||||
|
||||
cpa->hwDq(CPA::FL_NONE, sys, macAddr, "RXQ", "WireQ", 0, other_sys);
|
||||
anQ("RXQ", "RX FIFO Q");
|
||||
cpa->hwWe(CPA::FL_NONE, sys, macAddr, "RXQ", "WireQ", 0, other_sys);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1780,6 +1852,7 @@ IGbE::rxStateMachine()
|
|||
rxDescCache.writeback(0);
|
||||
|
||||
if (descLeft == 0) {
|
||||
anBegin("RXS", "Writeback Descriptors");
|
||||
rxDescCache.writeback(0);
|
||||
DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"
|
||||
" writeback and stopping ticking\n");
|
||||
|
@ -1791,6 +1864,7 @@ IGbE::rxStateMachine()
|
|||
|
||||
if (regs.rxdctl.wthresh() >= rxDescCache.descUsed()) {
|
||||
DPRINTF(EthernetSM, "RXS: Writing back because WTHRESH >= descUsed\n");
|
||||
anBegin("RXS", "Writeback Descriptors");
|
||||
if (regs.rxdctl.wthresh() < (cacheBlockSize()>>4))
|
||||
rxDescCache.writeback(regs.rxdctl.wthresh()-1);
|
||||
else
|
||||
|
@ -1800,11 +1874,14 @@ IGbE::rxStateMachine()
|
|||
if ((rxDescCache.descUnused() < regs.rxdctl.pthresh()) &&
|
||||
((rxDescCache.descLeft() - rxDescCache.descUnused()) > regs.rxdctl.hthresh())) {
|
||||
DPRINTF(EthernetSM, "RXS: Fetching descriptors because descUnused < PTHRESH\n");
|
||||
anBegin("RXS", "Fetch Descriptors");
|
||||
rxDescCache.fetchDescriptors();
|
||||
}
|
||||
|
||||
if (rxDescCache.descUnused() == 0) {
|
||||
anBegin("RXS", "Fetch Descriptors");
|
||||
rxDescCache.fetchDescriptors();
|
||||
anWe("RXS", rxDescCache.annUnusedCacheQ);
|
||||
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
|
||||
"fetching descriptors and stopping ticking\n");
|
||||
rxTick = false;
|
||||
|
@ -1819,18 +1896,24 @@ IGbE::rxStateMachine()
|
|||
}
|
||||
|
||||
if (!rxDescCache.descUnused()) {
|
||||
anBegin("RXS", "Fetch Descriptors");
|
||||
rxDescCache.fetchDescriptors();
|
||||
anWe("RXS", rxDescCache.annUnusedCacheQ);
|
||||
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");
|
||||
rxTick = false;
|
||||
DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n");
|
||||
return;
|
||||
}
|
||||
anPq("RXS", rxDescCache.annUnusedCacheQ);
|
||||
|
||||
if (rxFifo.empty()) {
|
||||
anWe("RXS", "RX FIFO Q");
|
||||
DPRINTF(EthernetSM, "RXS: RxFIFO empty, stopping ticking\n");
|
||||
rxTick = false;
|
||||
return;
|
||||
}
|
||||
anPq("RXS", "RX FIFO Q");
|
||||
anBegin("RXS", "Get Desc");
|
||||
|
||||
EthPacketPtr pkt;
|
||||
pkt = rxFifo.front();
|
||||
|
@ -1839,26 +1922,32 @@ IGbE::rxStateMachine()
|
|||
pktOffset = rxDescCache.writePacket(pkt, pktOffset);
|
||||
DPRINTF(EthernetSM, "RXS: Writing packet into memory\n");
|
||||
if (pktOffset == pkt->length) {
|
||||
anBegin( "RXS", "FIFO Dequeue");
|
||||
DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n");
|
||||
pktOffset = 0;
|
||||
anDq("RXS", "RX FIFO Q");
|
||||
rxFifo.pop();
|
||||
}
|
||||
|
||||
DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
|
||||
rxTick = false;
|
||||
rxDmaPacket = true;
|
||||
anBegin("RXS", "DMA Packet");
|
||||
}
|
||||
|
||||
void
|
||||
IGbE::txWire()
|
||||
{
|
||||
if (txFifo.empty()) {
|
||||
anWe("TXQ", "TX FIFO Q");
|
||||
txFifoTick = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
anPq("TXQ", "TX FIFO Q");
|
||||
if (etherInt->sendPacket(txFifo.front())) {
|
||||
cpa->hwQ(CPA::FL_NONE, sys, macAddr, "TXQ", "WireQ", 0);
|
||||
if (DTRACE(EthernetSM)) {
|
||||
IpPtr ip(txFifo.front());
|
||||
if (ip)
|
||||
|
@ -1867,6 +1956,8 @@ IGbE::txWire()
|
|||
else
|
||||
DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n");
|
||||
}
|
||||
anDq("TXQ", "TX FIFO Q");
|
||||
anBegin("TXQ", "Wire Send");
|
||||
DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
|
||||
txFifo.avail());
|
||||
|
||||
|
@ -1903,6 +1994,7 @@ IGbE::tick()
|
|||
void
|
||||
IGbE::ethTxDone()
|
||||
{
|
||||
anBegin("TXQ", "Send Done");
|
||||
// restart the tx state machines if they are stopped
|
||||
// fifo to send another packet
|
||||
// tx sm to put more data into the fifo
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "base/cp_annotate.hh"
|
||||
#include "base/inet.hh"
|
||||
#include "dev/etherdevice.hh"
|
||||
#include "dev/etherint.hh"
|
||||
|
@ -54,6 +55,7 @@ class IGbE : public EtherDevice
|
|||
{
|
||||
private:
|
||||
IGbEInt *etherInt;
|
||||
CPA *cpa;
|
||||
|
||||
// device registers
|
||||
iGbReg::Regs regs;
|
||||
|
@ -176,6 +178,35 @@ class IGbE : public EtherDevice
|
|||
*/
|
||||
void checkDrain();
|
||||
|
||||
void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) {
|
||||
cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st);
|
||||
}
|
||||
|
||||
void anQ(std::string sm, std::string q) {
|
||||
cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anDq(std::string sm, std::string q) {
|
||||
cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anPq(std::string sm, std::string q, int num = 1) {
|
||||
cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
|
||||
}
|
||||
|
||||
void anRq(std::string sm, std::string q, int num = 1) {
|
||||
cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
|
||||
}
|
||||
|
||||
void anWe(std::string sm, std::string q) {
|
||||
cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
void anWf(std::string sm, std::string q) {
|
||||
cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
class DescCache
|
||||
{
|
||||
|
@ -225,6 +256,10 @@ class IGbE : public EtherDevice
|
|||
EthPacketPtr pktPtr;
|
||||
|
||||
public:
|
||||
/** Annotate sm*/
|
||||
std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ,
|
||||
annUsedDescQ, annUnusedCacheQ, annDescQ;
|
||||
|
||||
DescCache(IGbE *i, const std::string n, int s)
|
||||
: igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0),
|
||||
pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this),
|
||||
|
@ -290,6 +325,10 @@ class IGbE : public EtherDevice
|
|||
DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb);
|
||||
|
||||
if (max_to_wb <= 0) {
|
||||
if (usedCache.size())
|
||||
igbe->anBegin(annSmWb, "Wait Alignment", CPA::FL_WAIT);
|
||||
else
|
||||
igbe->anWe(annSmWb, annUsedCacheQ);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -297,25 +336,30 @@ class IGbE : public EtherDevice
|
|||
|
||||
assert(!wbDelayEvent.scheduled());
|
||||
igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay);
|
||||
igbe->anBegin(annSmWb, "Prepare Writeback Desc");
|
||||
}
|
||||
|
||||
void writeback1()
|
||||
{
|
||||
// If we're draining delay issuing this DMA
|
||||
if (igbe->drainEvent) {
|
||||
if (igbe->getState() != SimObject::Running) {
|
||||
igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(EthernetDesc, "Beining DMA of %d descriptors\n", wbOut);
|
||||
DPRINTF(EthernetDesc, "Begining DMA of %d descriptors\n", wbOut);
|
||||
|
||||
for (int x = 0; x < wbOut; x++) {
|
||||
assert(usedCache.size());
|
||||
memcpy(&wbBuf[x], usedCache[x], sizeof(T));
|
||||
//delete usedCache[0];
|
||||
//usedCache.pop_front();
|
||||
igbe->anPq(annSmWb, annUsedCacheQ);
|
||||
igbe->anPq(annSmWb, annDescQ);
|
||||
igbe->anQ(annSmWb, annUsedDescQ);
|
||||
}
|
||||
|
||||
|
||||
igbe->anBegin(annSmWb, "Writeback Desc DMA");
|
||||
|
||||
assert(wbOut);
|
||||
igbe->dmaWrite(igbe->platform->pciToDma(descBase() + descHead() * sizeof(T)),
|
||||
wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf,
|
||||
|
@ -343,6 +387,18 @@ class IGbE : public EtherDevice
|
|||
|
||||
size_t free_cache = size - usedCache.size() - unusedCache.size();
|
||||
|
||||
if (!max_to_fetch)
|
||||
igbe->anWe(annSmFetch, annUnusedDescQ);
|
||||
else
|
||||
igbe->anPq(annSmFetch, annUnusedDescQ, max_to_fetch);
|
||||
|
||||
if (max_to_fetch) {
|
||||
if (!free_cache)
|
||||
igbe->anWf(annSmFetch, annDescQ);
|
||||
else
|
||||
igbe->anRq(annSmFetch, annDescQ, free_cache);
|
||||
}
|
||||
|
||||
max_to_fetch = std::min(max_to_fetch, free_cache);
|
||||
|
||||
|
||||
|
@ -360,16 +416,19 @@ class IGbE : public EtherDevice
|
|||
|
||||
assert(!fetchDelayEvent.scheduled());
|
||||
igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay);
|
||||
igbe->anBegin(annSmFetch, "Prepare Fetch Desc");
|
||||
}
|
||||
|
||||
void fetchDescriptors1()
|
||||
{
|
||||
// If we're draining delay issuing this DMA
|
||||
if (igbe->drainEvent) {
|
||||
if (igbe->getState() != SimObject::Running) {
|
||||
igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
igbe->anBegin(annSmFetch, "Fetch Desc");
|
||||
|
||||
DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n",
|
||||
descBase() + cachePnt * sizeof(T),
|
||||
igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),
|
||||
|
@ -387,10 +446,14 @@ class IGbE : public EtherDevice
|
|||
void fetchComplete()
|
||||
{
|
||||
T *newDesc;
|
||||
igbe->anBegin(annSmFetch, "Fetch Complete");
|
||||
for (int x = 0; x < curFetching; x++) {
|
||||
newDesc = new T;
|
||||
memcpy(newDesc, &fetchBuf[x], sizeof(T));
|
||||
unusedCache.push_back(newDesc);
|
||||
igbe->anDq(annSmFetch, annUnusedDescQ);
|
||||
igbe->anQ(annSmFetch, annUnusedCacheQ);
|
||||
igbe->anQ(annSmFetch, annDescQ);
|
||||
}
|
||||
|
||||
|
||||
|
@ -408,6 +471,16 @@ class IGbE : public EtherDevice
|
|||
DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n",
|
||||
oldCp, cachePnt);
|
||||
|
||||
if ((descTail() >= cachePnt ? (descTail() - cachePnt) : (descLen() -
|
||||
cachePnt)) == 0)
|
||||
{
|
||||
igbe->anWe(annSmFetch, annUnusedDescQ);
|
||||
} else if (!(size - usedCache.size() - unusedCache.size())) {
|
||||
igbe->anWf(annSmFetch, annDescQ);
|
||||
} else {
|
||||
igbe->anBegin(annSmFetch, "Wait", CPA::FL_WAIT);
|
||||
}
|
||||
|
||||
enableSm();
|
||||
igbe->checkDrain();
|
||||
}
|
||||
|
@ -419,6 +492,8 @@ class IGbE : public EtherDevice
|
|||
void wbComplete()
|
||||
{
|
||||
|
||||
igbe->anBegin(annSmWb, "Finish Writeback");
|
||||
|
||||
long curHead = descHead();
|
||||
#ifndef NDEBUG
|
||||
long oldHead = curHead;
|
||||
|
@ -428,6 +503,9 @@ class IGbE : public EtherDevice
|
|||
assert(usedCache.size());
|
||||
delete usedCache[0];
|
||||
usedCache.pop_front();
|
||||
|
||||
igbe->anDq(annSmWb, annUsedCacheQ);
|
||||
igbe->anDq(annSmWb, annDescQ);
|
||||
}
|
||||
|
||||
curHead += wbOut;
|
||||
|
@ -452,6 +530,10 @@ class IGbE : public EtherDevice
|
|||
|
||||
if (!wbOut) {
|
||||
igbe->checkDrain();
|
||||
if (usedCache.size())
|
||||
igbe->anBegin(annSmWb, "Wait", CPA::FL_WAIT);
|
||||
else
|
||||
igbe->anWe(annSmWb, annUsedCacheQ);
|
||||
}
|
||||
fetchAfterWb();
|
||||
}
|
||||
|
@ -747,6 +829,7 @@ class IGbE : public EtherDevice
|
|||
}
|
||||
IGbE(const Params *params);
|
||||
~IGbE() {}
|
||||
virtual void init();
|
||||
|
||||
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
|
||||
|
||||
|
|
Loading…
Reference in a new issue