Add the ability to specify a think time before descriptor fetch/writeback starts/ends as well as after read/write dmas
This commit is contained in:
parent
549c43b2d0
commit
6248e12704
3 changed files with 71 additions and 21 deletions
|
@ -98,6 +98,13 @@ class IGbE(EtherDevice):
|
||||||
InterruptLine = 0x1e
|
InterruptLine = 0x1e
|
||||||
InterruptPin = 0x01
|
InterruptPin = 0x01
|
||||||
BAR0Size = '128kB'
|
BAR0Size = '128kB'
|
||||||
|
wb_delay = Param.Latency('10ns', "delay before desc writeback occurs")
|
||||||
|
fetch_delay = Param.Latency('10ns', "delay before desc fetch occurs")
|
||||||
|
fetch_comp_delay = Param.Latency('10ns', "delay after desc fetch occurs")
|
||||||
|
wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs")
|
||||||
|
tx_read_delay = Param.Latency('0ns', "delay after tx dma read")
|
||||||
|
rx_write_delay = Param.Latency('0ns', "delay after rx dma read")
|
||||||
|
|
||||||
|
|
||||||
class EtherDevBase(EtherDevice):
|
class EtherDevBase(EtherDevice):
|
||||||
type = 'EtherDevBase'
|
type = 'EtherDevBase'
|
||||||
|
|
|
@ -57,7 +57,11 @@ using namespace Net;
|
||||||
IGbE::IGbE(const Params *p)
|
IGbE::IGbE(const Params *p)
|
||||||
: EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control),
|
: EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control),
|
||||||
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
|
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
|
||||||
txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this),
|
txTick(false), txFifoTick(false), rxDmaPacket(false),
|
||||||
|
fetchDelay(p->fetch_delay), wbDelay(p->wb_delay),
|
||||||
|
fetchCompDelay(p->fetch_comp_delay), wbCompDelay(p->wb_comp_delay),
|
||||||
|
rxWriteDelay(p->rx_write_delay), txReadDelay(p->tx_read_delay),
|
||||||
|
rdtrEvent(this), radvEvent(this),
|
||||||
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
|
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
|
||||||
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
|
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
|
||||||
txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size),
|
txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size),
|
||||||
|
@ -714,7 +718,7 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet)
|
||||||
pktPtr = packet;
|
pktPtr = packet;
|
||||||
pktDone = false;
|
pktDone = false;
|
||||||
igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf),
|
igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf),
|
||||||
packet->length, &pktEvent, packet->data);
|
packet->length, &pktEvent, packet->data, igbe->rxWriteDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -932,7 +936,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
|
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
|
||||||
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
||||||
TxdOp::getLen(desc), &pktEvent, p->data + p->length);
|
TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,11 @@ class IGbE : public EtherDevice
|
||||||
|
|
||||||
bool rxDmaPacket;
|
bool rxDmaPacket;
|
||||||
|
|
||||||
|
// Delays in managaging descriptors
|
||||||
|
Tick fetchDelay, wbDelay;
|
||||||
|
Tick fetchCompDelay, wbCompDelay;
|
||||||
|
Tick rxWriteDelay, txReadDelay;
|
||||||
|
|
||||||
// Event and function to deal with RDTR timer expiring
|
// Event and function to deal with RDTR timer expiring
|
||||||
void rdtrProcess() {
|
void rdtrProcess() {
|
||||||
rxDescCache.writeback(0);
|
rxDescCache.writeback(0);
|
||||||
|
@ -217,7 +222,8 @@ class IGbE : public EtherDevice
|
||||||
public:
|
public:
|
||||||
DescCache(IGbE *i, const std::string n, int s)
|
DescCache(IGbE *i, const std::string n, int s)
|
||||||
: igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0),
|
: igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0),
|
||||||
pktPtr(NULL), fetchEvent(this), wbEvent(this)
|
pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this),
|
||||||
|
fetchEvent(this), wbEvent(this)
|
||||||
{
|
{
|
||||||
fetchBuf = new T[size];
|
fetchBuf = new T[size];
|
||||||
wbBuf = new T[size];
|
wbBuf = new T[size];
|
||||||
|
@ -243,6 +249,21 @@ class IGbE : public EtherDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeback(Addr aMask)
|
void writeback(Addr aMask)
|
||||||
|
{
|
||||||
|
if (wbOut) {
|
||||||
|
if (aMask < wbAlignment) {
|
||||||
|
moreToWb = true;
|
||||||
|
wbAlignment = aMask;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wbAlignment = aMask;
|
||||||
|
if (!wbDelayEvent.scheduled())
|
||||||
|
wbDelayEvent.schedule(igbe->wbDelay + curTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeback1()
|
||||||
{
|
{
|
||||||
int curHead = descHead();
|
int curHead = descHead();
|
||||||
int max_to_wb = usedCache.size();
|
int max_to_wb = usedCache.size();
|
||||||
|
@ -252,26 +273,13 @@ class IGbE : public EtherDevice
|
||||||
curHead, descTail(), descLen(), cachePnt, max_to_wb,
|
curHead, descTail(), descLen(), cachePnt, max_to_wb,
|
||||||
descLeft());
|
descLeft());
|
||||||
|
|
||||||
// Check if this writeback is less restrictive that the previous
|
|
||||||
// and if so setup another one immediately following it
|
|
||||||
if (wbOut && (aMask < wbAlignment)) {
|
|
||||||
moreToWb = true;
|
|
||||||
wbAlignment = aMask;
|
|
||||||
DPRINTF(EthernetDesc, "Writing back already in process, returning\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
moreToWb = false;
|
|
||||||
wbAlignment = aMask;
|
|
||||||
|
|
||||||
if (max_to_wb + curHead >= descLen()) {
|
if (max_to_wb + curHead >= descLen()) {
|
||||||
max_to_wb = descLen() - curHead;
|
max_to_wb = descLen() - curHead;
|
||||||
moreToWb = true;
|
moreToWb = true;
|
||||||
// this is by definition aligned correctly
|
// this is by definition aligned correctly
|
||||||
} else if (aMask != 0) {
|
} else if (wbAlignment != 0) {
|
||||||
// align the wb point to the mask
|
// align the wb point to the mask
|
||||||
max_to_wb = max_to_wb & ~aMask;
|
max_to_wb = max_to_wb & ~wbAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb);
|
DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb);
|
||||||
|
@ -291,13 +299,22 @@ class IGbE : public EtherDevice
|
||||||
|
|
||||||
assert(wbOut);
|
assert(wbOut);
|
||||||
igbe->dmaWrite(igbe->platform->pciToDma(descBase() + curHead * sizeof(T)),
|
igbe->dmaWrite(igbe->platform->pciToDma(descBase() + curHead * sizeof(T)),
|
||||||
wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf);
|
wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf,
|
||||||
|
igbe->wbCompDelay);
|
||||||
}
|
}
|
||||||
|
EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;
|
||||||
|
|
||||||
/** Fetch a chunk of descriptors into the descriptor cache.
|
/** Fetch a chunk of descriptors into the descriptor cache.
|
||||||
* Calls fetchComplete when the memory system returns the data
|
* Calls fetchComplete when the memory system returns the data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void fetchDescriptors()
|
void fetchDescriptors()
|
||||||
|
{
|
||||||
|
if (!fetchDelayEvent.scheduled())
|
||||||
|
fetchDelayEvent.schedule(igbe->fetchDelay + curTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetchDescriptors1()
|
||||||
{
|
{
|
||||||
size_t max_to_fetch;
|
size_t max_to_fetch;
|
||||||
|
|
||||||
|
@ -331,9 +348,11 @@ class IGbE : public EtherDevice
|
||||||
curFetching * sizeof(T));
|
curFetching * sizeof(T));
|
||||||
assert(curFetching);
|
assert(curFetching);
|
||||||
igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),
|
igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),
|
||||||
curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf);
|
curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf,
|
||||||
|
igbe->fetchCompDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;
|
||||||
|
|
||||||
/** Called by event when dma to read descriptors is completed
|
/** Called by event when dma to read descriptors is completed
|
||||||
*/
|
*/
|
||||||
|
@ -391,6 +410,7 @@ class IGbE : public EtherDevice
|
||||||
// If we still have more to wb, call wb now
|
// If we still have more to wb, call wb now
|
||||||
intAfterWb();
|
intAfterWb();
|
||||||
if (moreToWb) {
|
if (moreToWb) {
|
||||||
|
moreToWb = false;
|
||||||
DPRINTF(EthernetDesc, "Writeback has more todo\n");
|
DPRINTF(EthernetDesc, "Writeback has more todo\n");
|
||||||
writeback(wbAlignment);
|
writeback(wbAlignment);
|
||||||
}
|
}
|
||||||
|
@ -463,6 +483,16 @@ class IGbE : public EtherDevice
|
||||||
arrayParamOut(os, csprintf("unusedCache_%d", x),
|
arrayParamOut(os, csprintf("unusedCache_%d", x),
|
||||||
(uint8_t*)unusedCache[x],sizeof(T));
|
(uint8_t*)unusedCache[x],sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tick fetch_delay = 0, wb_delay = 0;
|
||||||
|
if (fetchDelayEvent.scheduled())
|
||||||
|
fetch_delay = fetchDelayEvent.when();
|
||||||
|
SERIALIZE_SCALAR(fetch_delay);
|
||||||
|
if (wbDelayEvent.scheduled())
|
||||||
|
wb_delay = wbDelayEvent.when();
|
||||||
|
SERIALIZE_SCALAR(wb_delay);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion)
|
virtual void unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
@ -491,6 +521,15 @@ class IGbE : public EtherDevice
|
||||||
(uint8_t*)temp,sizeof(T));
|
(uint8_t*)temp,sizeof(T));
|
||||||
unusedCache.push_back(temp);
|
unusedCache.push_back(temp);
|
||||||
}
|
}
|
||||||
|
Tick fetch_delay = 0, wb_delay = 0;
|
||||||
|
UNSERIALIZE_SCALAR(fetch_delay);
|
||||||
|
UNSERIALIZE_SCALAR(wb_delay);
|
||||||
|
if (fetch_delay)
|
||||||
|
fetchDelayEvent.schedule(fetch_delay);
|
||||||
|
if (wb_delay)
|
||||||
|
wbDelayEvent.schedule(wb_delay);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
virtual bool hasOutstandingEvents() {
|
virtual bool hasOutstandingEvents() {
|
||||||
return wbEvent.scheduled() || fetchEvent.scheduled();
|
return wbEvent.scheduled() || fetchEvent.scheduled();
|
||||||
|
|
Loading…
Reference in a new issue