Merge zizzer:/bk/newmem

into  zeep.pool:/z/saidi/work/m5.newmem

--HG--
extra : convert_revision : 2f7f50f4ad31f741c0c67db96e49d30ca078fc94
This commit is contained in:
Ali Saidi 2007-03-29 22:01:34 -04:00
commit c46e946c94
8 changed files with 487 additions and 97 deletions

View file

@ -647,11 +647,9 @@ void MiscRegFile::setReg(int miscReg,
return; return;
case MISCREG_CWP: case MISCREG_CWP:
new_val = val >= NWindows ? NWindows - 1 : val; new_val = val >= NWindows ? NWindows - 1 : val;
if (val >= NWindows) { if (val >= NWindows)
new_val = NWindows - 1; new_val = NWindows - 1;
warn("Attempted to set the CWP to %d with NWindows = %d\n",
val, NWindows);
}
tc->changeRegFileContext(CONTEXT_CWP, new_val); tc->changeRegFileContext(CONTEXT_CWP, new_val);
break; break;
case MISCREG_GL: case MISCREG_GL:

View file

@ -55,10 +55,10 @@ using namespace iGbReg;
using namespace Net; using namespace Net;
IGbE::IGbE(Params *p) IGbE::IGbE(Params *p)
: PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control), : PciDev(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), rdtrEvent(this), radvEvent(this), tadvEvent(this), txTick(false), txFifoTick(false), rdtrEvent(this), radvEvent(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), clock(p->clock) txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock)
{ {
@ -223,6 +223,7 @@ IGbE::read(PacketPtr pkt)
pkt->set<uint32_t>(regs.rdtr()); pkt->set<uint32_t>(regs.rdtr());
if (regs.rdtr.fpd()) { if (regs.rdtr.fpd()) {
rxDescCache.writeback(0); rxDescCache.writeback(0);
DPRINTF(EthernetIntr, "Posting interrupt because of RDTR.FPD write\n");
postInterrupt(IT_RXT); postInterrupt(IT_RXT);
regs.rdtr.fpd(0); regs.rdtr.fpd(0);
} }
@ -411,6 +412,7 @@ IGbE::write(PacketPtr pkt)
regs.itr = val; regs.itr = val;
break; break;
case REG_ICS: case REG_ICS:
DPRINTF(EthernetIntr, "Posting interrupt because of ICS write\n");
postInterrupt((IntTypes)val); postInterrupt((IntTypes)val);
break; break;
case REG_IMS: case REG_IMS:
@ -429,6 +431,7 @@ IGbE::write(PacketPtr pkt)
regs.rctl = val; regs.rctl = val;
if (regs.rctl.rst()) { if (regs.rctl.rst()) {
rxDescCache.reset(); rxDescCache.reset();
DPRINTF(EthernetSM, "RXS: Got RESET!\n");
rxFifo.clear(); rxFifo.clear();
regs.rctl.rst(0); regs.rctl.rst(0);
} }
@ -568,8 +571,8 @@ IGbE::postInterrupt(IntTypes t, bool now)
} else { } else {
DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n", DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
Clock::Int::ns * 256 * regs.itr.interval()); Clock::Int::ns * 256 * regs.itr.interval());
assert(!interEvent.scheduled()); if (!interEvent.scheduled())
interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
} }
} }
} }
@ -676,39 +679,39 @@ IGbE::RxDescCache::pktComplete()
// no support for anything but starting at 0 // no support for anything but starting at 0
assert(igbe->regs.rxcsum.pcss() == 0); assert(igbe->regs.rxcsum.pcss() == 0);
DPRINTF(EthernetDesc, "RxDesc: Packet written to memory updating Descriptor\n"); DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n");
uint8_t status = RXDS_DD | RXDS_EOP; uint8_t status = RXDS_DD | RXDS_EOP;
uint8_t err = 0; uint8_t err = 0;
IpPtr ip(pktPtr); IpPtr ip(pktPtr);
if (ip) { if (ip) {
if (igbe->regs.rxcsum.ipofld()) { if (igbe->regs.rxcsum.ipofld()) {
DPRINTF(EthernetDesc, "RxDesc: Checking IP checksum\n"); DPRINTF(EthernetDesc, "Checking IP checksum\n");
status |= RXDS_IPCS; status |= RXDS_IPCS;
desc->csum = htole(cksum(ip)); desc->csum = htole(cksum(ip));
if (cksum(ip) != 0) { if (cksum(ip) != 0) {
err |= RXDE_IPE; err |= RXDE_IPE;
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); DPRINTF(EthernetDesc, "Checksum is bad!!\n");
} }
} }
TcpPtr tcp(ip); TcpPtr tcp(ip);
if (tcp && igbe->regs.rxcsum.tuofld()) { if (tcp && igbe->regs.rxcsum.tuofld()) {
DPRINTF(EthernetDesc, "RxDesc: Checking TCP checksum\n"); DPRINTF(EthernetDesc, "Checking TCP checksum\n");
status |= RXDS_TCPCS; status |= RXDS_TCPCS;
desc->csum = htole(cksum(tcp)); desc->csum = htole(cksum(tcp));
if (cksum(tcp) != 0) { if (cksum(tcp) != 0) {
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE; err |= RXDE_TCPE;
} }
} }
UdpPtr udp(ip); UdpPtr udp(ip);
if (udp && igbe->regs.rxcsum.tuofld()) { if (udp && igbe->regs.rxcsum.tuofld()) {
DPRINTF(EthernetDesc, "RxDesc: Checking UDP checksum\n"); DPRINTF(EthernetDesc, "Checking UDP checksum\n");
status |= RXDS_UDPCS; status |= RXDS_UDPCS;
desc->csum = htole(cksum(udp)); desc->csum = htole(cksum(udp));
if (cksum(tcp) != 0) { if (cksum(tcp) != 0) {
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE; err |= RXDE_TCPE;
} }
} }
@ -748,15 +751,18 @@ IGbE::RxDescCache::pktComplete()
// If the packet is small enough, interrupt appropriately // If the packet is small enough, interrupt appropriately
// I wonder if this is delayed or not?! // I wonder if this is delayed or not?!
if (pktPtr->length <= igbe->regs.rsrpd.idv()) if (pktPtr->length <= igbe->regs.rsrpd.idv()) {
DPRINTF(EthernetSM, "RXS: Posting IT_SRPD beacuse small packet received\n");
igbe->postInterrupt(IT_SRPD); igbe->postInterrupt(IT_SRPD);
}
DPRINTF(EthernetDesc, "RxDesc: Processing of this descriptor complete\n"); DPRINTF(EthernetDesc, "Processing of this descriptor complete\n");
unusedCache.pop_front(); unusedCache.pop_front();
usedCache.push_back(desc); usedCache.push_back(desc);
pktPtr = NULL; pktPtr = NULL;
enableSm(); enableSm();
pktDone = true; pktDone = true;
igbe->checkDrain();
} }
void void
@ -776,11 +782,33 @@ IGbE::RxDescCache::packetDone()
return false; return false;
} }
bool
IGbE::RxDescCache::hasOutstandingEvents()
{
return pktEvent.scheduled() || wbEvent.scheduled() ||
fetchEvent.scheduled();
}
void
IGbE::RxDescCache::serialize(std::ostream &os)
{
DescCache<RxDesc>::serialize(os);
SERIALIZE_SCALAR(pktDone);
}
void
IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string &section)
{
DescCache<RxDesc>::unserialize(cp, section);
UNSERIALIZE_SCALAR(pktDone);
}
///////////////////////////////////// IGbE::TxDesc ///////////////////////////////// ///////////////////////////////////// IGbE::TxDesc /////////////////////////////////
IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
: DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false), : DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false),
hLen(0), pktEvent(this) pktEvent(this)
{ {
} }
@ -792,10 +820,10 @@ IGbE::TxDescCache::getPacketSize()
TxDesc *desc; TxDesc *desc;
DPRINTF(EthernetDesc, "TxDesc: Starting processing of descriptor\n"); DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) { while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
DPRINTF(EthernetDesc, "TxDesc: Got context descriptor type... skipping\n"); DPRINTF(EthernetDesc, "Got context descriptor type... skipping\n");
// I think we can just ignore these for now? // I think we can just ignore these for now?
desc = unusedCache.front(); desc = unusedCache.front();
@ -813,7 +841,7 @@ IGbE::TxDescCache::getPacketSize()
if (!unusedCache.size()) if (!unusedCache.size())
return -1; return -1;
DPRINTF(EthernetDesc, "TxDesc: Next TX packet is %d bytes\n", DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
TxdOp::getLen(unusedCache.front())); TxdOp::getLen(unusedCache.front()));
return TxdOp::getLen(unusedCache.front()); return TxdOp::getLen(unusedCache.front());
@ -833,9 +861,9 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
pktWaiting = true; pktWaiting = true;
DPRINTF(EthernetDesc, "TxDesc: Starting DMA of packet\n"); DPRINTF(EthernetDesc, "Starting DMA of packet\n");
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
TxdOp::getLen(desc), &pktEvent, p->data + hLen); TxdOp::getLen(desc), &pktEvent, p->data + p->length);
} }
@ -848,7 +876,7 @@ IGbE::TxDescCache::pktComplete()
assert(unusedCache.size()); assert(unusedCache.size());
assert(pktPtr); assert(pktPtr);
DPRINTF(EthernetDesc, "TxDesc: DMA of packet complete\n"); DPRINTF(EthernetDesc, "DMA of packet complete\n");
desc = unusedCache.front(); desc = unusedCache.front();
@ -857,20 +885,21 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
if (!TxdOp::eop(desc)) { if (!TxdOp::eop(desc)) {
assert(hLen == 0); // This only supports two descriptors per tx packet
hLen = TxdOp::getLen(desc); assert(pktPtr->length == 0);
pktPtr->length = TxdOp::getLen(desc);
unusedCache.pop_front(); unusedCache.pop_front();
usedCache.push_back(desc); usedCache.push_back(desc);
pktDone = true; pktDone = true;
pktWaiting = false; pktWaiting = false;
pktPtr = NULL; pktPtr = NULL;
DPRINTF(EthernetDesc, "TxDesc: Partial Packet Descriptor Done\n"); DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n");
return; return;
} }
// Set the length of the data in the EtherPacket // Set the length of the data in the EtherPacket
pktPtr->length = TxdOp::getLen(desc) + hLen; pktPtr->length += TxdOp::getLen(desc);
// no support for vlans // no support for vlans
assert(!TxdOp::vle(desc)); assert(!TxdOp::vle(desc));
@ -888,33 +917,33 @@ IGbE::TxDescCache::pktComplete()
// Checksums are only ofloaded for new descriptor types // Checksums are only ofloaded for new descriptor types
if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) { if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
DPRINTF(EthernetDesc, "TxDesc: Calculating checksums for packet\n"); DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
IpPtr ip(pktPtr); IpPtr ip(pktPtr);
if (TxdOp::ixsm(desc)) { if (TxdOp::ixsm(desc)) {
ip->sum(0); ip->sum(0);
ip->sum(cksum(ip)); ip->sum(cksum(ip));
DPRINTF(EthernetDesc, "TxDesc: Calculated IP checksum\n"); DPRINTF(EthernetDesc, "Calculated IP checksum\n");
} }
if (TxdOp::txsm(desc)) { if (TxdOp::txsm(desc)) {
if (isTcp) { if (isTcp) {
TcpPtr tcp(ip); TcpPtr tcp(ip);
tcp->sum(0); tcp->sum(0);
tcp->sum(cksum(tcp)); tcp->sum(cksum(tcp));
DPRINTF(EthernetDesc, "TxDesc: Calculated TCP checksum\n"); DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
} else { } else {
UdpPtr udp(ip); UdpPtr udp(ip);
udp->sum(0); udp->sum(0);
udp->sum(cksum(udp)); udp->sum(cksum(udp));
DPRINTF(EthernetDesc, "TxDesc: Calculated UDP checksum\n"); DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
} }
} }
} }
if (TxdOp::ide(desc)) { if (TxdOp::ide(desc)) {
// Deal with the rx timer interrupts // Deal with the rx timer interrupts
DPRINTF(EthernetDesc, "TxDesc: Descriptor had IDE set\n"); DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
if (igbe->regs.tidv.idv()) { if (igbe->regs.tidv.idv()) {
DPRINTF(EthernetDesc, "TxDesc: setting tidv\n"); DPRINTF(EthernetDesc, "setting tidv\n");
if (igbe->tidvEvent.scheduled()) if (igbe->tidvEvent.scheduled())
igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
igbe->intClock()); igbe->intClock());
@ -924,7 +953,7 @@ IGbE::TxDescCache::pktComplete()
} }
if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) { if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
DPRINTF(EthernetDesc, "TxDesc: setting tadv\n"); DPRINTF(EthernetDesc, "setting tadv\n");
if (!igbe->tadvEvent.scheduled()) if (!igbe->tadvEvent.scheduled())
igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() * igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() *
igbe->intClock()); igbe->intClock());
@ -939,17 +968,34 @@ IGbE::TxDescCache::pktComplete()
pktWaiting = false; pktWaiting = false;
pktPtr = NULL; pktPtr = NULL;
hLen = 0; DPRINTF(EthernetDesc, "Descriptor Done\n");
DPRINTF(EthernetDesc, "TxDesc: Descriptor Done\n");
if (igbe->regs.txdctl.wthresh() == 0) { if (igbe->regs.txdctl.wthresh() == 0) {
DPRINTF(EthernetDesc, "TxDesc: WTHRESH == 0, writing back descriptor\n"); DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
writeback(0); writeback(0);
} else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) { } else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
DPRINTF(EthernetDesc, "TxDesc: used > WTHRESH, writing back descriptor\n"); DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
writeback((igbe->cacheBlockSize()-1)>>4); writeback((igbe->cacheBlockSize()-1)>>4);
} }
igbe->checkDrain();
}
void
IGbE::TxDescCache::serialize(std::ostream &os)
{
DescCache<TxDesc>::serialize(os);
SERIALIZE_SCALAR(pktDone);
SERIALIZE_SCALAR(isTcp);
SERIALIZE_SCALAR(pktWaiting);
}
void
IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string &section)
{
DescCache<TxDesc>::unserialize(cp, section);
UNSERIALIZE_SCALAR(pktDone);
UNSERIALIZE_SCALAR(isTcp);
UNSERIALIZE_SCALAR(pktWaiting);
} }
bool bool
@ -969,7 +1015,12 @@ IGbE::TxDescCache::enableSm()
igbe->restartClock(); igbe->restartClock();
} }
bool
IGbE::TxDescCache::hasOutstandingEvents()
{
return pktEvent.scheduled() || wbEvent.scheduled() ||
fetchEvent.scheduled();
}
///////////////////////////////////// IGbE ///////////////////////////////// ///////////////////////////////////// IGbE /////////////////////////////////
@ -977,10 +1028,61 @@ IGbE::TxDescCache::enableSm()
void void
IGbE::restartClock() IGbE::restartClock()
{ {
if (!tickEvent.scheduled() && (rxTick || txTick)) if (!tickEvent.scheduled() && (rxTick || txTick) && getState() ==
SimObject::Running)
tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1)); tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1));
} }
unsigned int
IGbE::drain(Event *de)
{
unsigned int count;
count = pioPort->drain(de) + dmaPort->drain(de);
if (rxDescCache.hasOutstandingEvents() ||
txDescCache.hasOutstandingEvents()) {
count++;
drainEvent = de;
}
txFifoTick = false;
txTick = false;
rxTick = false;
if (tickEvent.scheduled())
tickEvent.deschedule();
if (count)
changeState(Draining);
else
changeState(Drained);
return count;
}
void
IGbE::resume()
{
SimObject::resume();
txFifoTick = true;
txTick = true;
rxTick = true;
restartClock();
}
void
IGbE::checkDrain()
{
if (!drainEvent)
return;
if (rxDescCache.hasOutstandingEvents() ||
txDescCache.hasOutstandingEvents()) {
drainEvent->process();
drainEvent = NULL;
}
}
void void
IGbE::txStateMachine() IGbE::txStateMachine()
@ -998,8 +1100,10 @@ IGbE::txStateMachine()
bool success; bool success;
DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n"); DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
success = txFifo.push(txPacket); success = txFifo.push(txPacket);
txFifoTick = true;
assert(success); assert(success);
txPacket = NULL; txPacket = NULL;
txDescCache.writeback((cacheBlockSize()-1)>>4);
return; return;
} }
@ -1021,6 +1125,7 @@ IGbE::txStateMachine()
txDescCache.writeback(0); txDescCache.writeback(0);
txTick = false; txTick = false;
postInterrupt(IT_TXQE, true); postInterrupt(IT_TXQE, true);
return;
} }
@ -1038,11 +1143,17 @@ IGbE::txStateMachine()
"DMA of next packet\n", size); "DMA of next packet\n", size);
txFifo.reserve(size); txFifo.reserve(size);
txDescCache.getPacketData(txPacket); txDescCache.getPacketData(txPacket);
} else { } else if (size <= 0) {
DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n"); DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");
txDescCache.writeback(0); txDescCache.writeback(0);
} else {
DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "
"available in FIFO\n");
txDescCache.writeback((cacheBlockSize()-1)>>4);
txTick = false;
} }
return; return;
} }
} }
@ -1095,9 +1206,9 @@ IGbE::rxStateMachine()
} }
if (descLeft == 0) { if (descLeft == 0) {
DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing writeback\n"); DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"
" writeback and stopping ticking\n");
rxDescCache.writeback(0); rxDescCache.writeback(0);
DPRINTF(EthernetSM, "RXS: No descriptors left, stopping ticking\n");
rxTick = false; rxTick = false;
} }
@ -1119,9 +1230,9 @@ IGbE::rxStateMachine()
} }
if (rxDescCache.descUnused() == 0) { if (rxDescCache.descUnused() == 0) {
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n"); DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
"fetching descriptors and stopping ticking\n");
rxTick = false; rxTick = false;
DPRINTF(EthernetSM, "RXS: Fetching descriptors because none available\n");
rxDescCache.fetchDescriptors(); rxDescCache.fetchDescriptors();
} }
return; return;
@ -1159,15 +1270,18 @@ void
IGbE::txWire() IGbE::txWire()
{ {
if (txFifo.empty()) { if (txFifo.empty()) {
txFifoTick = false;
return; return;
} }
txTick = true;
if (etherInt->sendPacket(txFifo.front())) { if (etherInt->sendPacket(txFifo.front())) {
DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n", DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
txFifo.avail()); txFifo.avail());
txFifo.pop(); txFifo.pop();
} else {
// We'll get woken up when the packet ethTxDone() gets called
txFifoTick = false;
} }
} }
@ -1180,34 +1294,133 @@ IGbE::tick()
if (rxTick) if (rxTick)
rxStateMachine(); rxStateMachine();
if (txTick) { if (txTick)
txStateMachine(); txStateMachine();
txWire();
}
if (rxTick || txTick) if (txFifoTick)
txWire();
if (rxTick || txTick || txFifoTick)
tickEvent.schedule(curTick + cycles(1)); tickEvent.schedule(curTick + cycles(1));
} }
void void
IGbE::ethTxDone() IGbE::ethTxDone()
{ {
// restart the state machines if they are stopped // restart the tx state machines if they are stopped
// fifo to send another packet
// tx sm to put more data into the fifo
txFifoTick = true;
txTick = true; txTick = true;
restartClock(); restartClock();
DPRINTF(Ethernet, "TxFIFO: Transmission complete\n"); DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n");
} }
void void
IGbE::serialize(std::ostream &os) IGbE::serialize(std::ostream &os)
{ {
panic("Need to implemenet\n"); PciDev::serialize(os);
regs.serialize(os);
SERIALIZE_SCALAR(eeOpBits);
SERIALIZE_SCALAR(eeAddrBits);
SERIALIZE_SCALAR(eeDataBits);
SERIALIZE_SCALAR(eeOpcode);
SERIALIZE_SCALAR(eeAddr);
SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.serialize("rxfifo", os);
txFifo.serialize("txfifo", os);
bool txPktExists = txPacket;
SERIALIZE_SCALAR(txPktExists);
if (txPktExists)
txPacket->serialize("txpacket", os);
Tick rdtr_time = 0, radv_time = 0, tidv_time = 0, tadv_time = 0,
inter_time = 0;
if (rdtrEvent.scheduled())
rdtr_time = rdtrEvent.when();
SERIALIZE_SCALAR(rdtr_time);
if (radvEvent.scheduled())
radv_time = radvEvent.when();
SERIALIZE_SCALAR(radv_time);
if (tidvEvent.scheduled())
rdtr_time = tidvEvent.when();
SERIALIZE_SCALAR(tidv_time);
if (tadvEvent.scheduled())
rdtr_time = tadvEvent.when();
SERIALIZE_SCALAR(tadv_time);
if (interEvent.scheduled())
rdtr_time = interEvent.when();
SERIALIZE_SCALAR(inter_time);
nameOut(os, csprintf("%s.TxDescCache", name()));
txDescCache.serialize(os);
nameOut(os, csprintf("%s.RxDescCache", name()));
rxDescCache.serialize(os);
} }
void void
IGbE::unserialize(Checkpoint *cp, const std::string &section) IGbE::unserialize(Checkpoint *cp, const std::string &section)
{ {
panic("Need to implemenet\n"); PciDev::unserialize(cp, section);
regs.unserialize(cp, section);
UNSERIALIZE_SCALAR(eeOpBits);
UNSERIALIZE_SCALAR(eeAddrBits);
UNSERIALIZE_SCALAR(eeDataBits);
UNSERIALIZE_SCALAR(eeOpcode);
UNSERIALIZE_SCALAR(eeAddr);
UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.unserialize("rxfifo", cp, section);
txFifo.unserialize("txfifo", cp, section);
bool txPktExists;
UNSERIALIZE_SCALAR(txPktExists);
if (txPktExists) {
txPacket = new EthPacketData(16384);
txPacket->unserialize("txpacket", cp, section);
}
rxTick = true;
txTick = true;
txFifoTick = true;
Tick rdtr_time, radv_time, tidv_time, tadv_time, inter_time;
UNSERIALIZE_SCALAR(rdtr_time);
UNSERIALIZE_SCALAR(radv_time);
UNSERIALIZE_SCALAR(tidv_time);
UNSERIALIZE_SCALAR(tadv_time);
UNSERIALIZE_SCALAR(inter_time);
if (rdtr_time)
rdtrEvent.schedule(rdtr_time);
if (radv_time)
radvEvent.schedule(radv_time);
if (tidv_time)
tidvEvent.schedule(tidv_time);
if (tadv_time)
tadvEvent.schedule(tadv_time);
if (inter_time)
interEvent.schedule(inter_time);
txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section));
rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section));
} }

View file

@ -62,8 +62,10 @@ class IGbE : public PciDev
uint8_t eeOpcode, eeAddr; uint8_t eeOpcode, eeAddr;
uint16_t flash[iGbReg::EEPROM_SIZE]; uint16_t flash[iGbReg::EEPROM_SIZE];
// The drain event if we have one
Event *drainEvent;
// cached parameters from params struct // cached parameters from params struct
Tick tickRate;
bool useFlowControl; bool useFlowControl;
// packet fifos // packet fifos
@ -76,24 +78,44 @@ class IGbE : public PciDev
// Should to Rx/Tx State machine tick? // Should to Rx/Tx State machine tick?
bool rxTick; bool rxTick;
bool txTick; bool txTick;
bool txFifoTick;
// Event and function to deal with RDTR timer expiring // Event and function to deal with RDTR timer expiring
void rdtrProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); } void rdtrProcess() {
rxDescCache.writeback(0);
DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n");
postInterrupt(iGbReg::IT_RXT, true);
}
//friend class EventWrapper<IGbE, &IGbE::rdtrProcess>; //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent; EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
// Event and function to deal with RADV timer expiring // Event and function to deal with RADV timer expiring
void radvProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); } void radvProcess() {
rxDescCache.writeback(0);
DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n");
postInterrupt(iGbReg::IT_RXT, true);
}
//friend class EventWrapper<IGbE, &IGbE::radvProcess>; //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
EventWrapper<IGbE, &IGbE::radvProcess> radvEvent; EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
// Event and function to deal with TADV timer expiring // Event and function to deal with TADV timer expiring
void tadvProcess() { postInterrupt(iGbReg::IT_TXDW, true); } void tadvProcess() {
txDescCache.writeback(0);
DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n");
postInterrupt(iGbReg::IT_TXDW, true);
}
//friend class EventWrapper<IGbE, &IGbE::tadvProcess>; //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent; EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
// Event and function to deal with TIDV timer expiring // Event and function to deal with TIDV timer expiring
void tidvProcess() { postInterrupt(iGbReg::IT_TXDW, true); }; void tidvProcess() {
txDescCache.writeback(0);
DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n");
postInterrupt(iGbReg::IT_TXDW, true);
}
//friend class EventWrapper<IGbE, &IGbE::tidvProcess>; //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent; EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
@ -131,8 +153,15 @@ class IGbE : public PciDev
Tick intClock() { return Clock::Int::ns * 1024; } Tick intClock() { return Clock::Int::ns * 1024; }
/** This function is used to restart the clock so it can handle things like
* draining and resume in one place. */
void restartClock(); void restartClock();
/** Check if all the draining things that need to occur have occured and
* handle the drain event if so.
*/
void checkDrain();
template<class T> template<class T>
class DescCache class DescCache
{ {
@ -202,8 +231,10 @@ class IGbE : public PciDev
*/ */
void areaChanged() void areaChanged()
{ {
if (usedCache.size() > 0 || unusedCache.size() > 0) if (usedCache.size() > 0 || curFetching || wbOut)
panic("Descriptor Address, Length or Head changed. Bad\n"); panic("Descriptor Address, Length or Head changed. Bad\n");
reset();
} }
void writeback(Addr aMask) void writeback(Addr aMask)
@ -229,7 +260,7 @@ class IGbE : public PciDev
moreToWb = false; moreToWb = false;
wbAlignment = aMask; 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
@ -265,10 +296,14 @@ class IGbE : public PciDev
*/ */
void fetchDescriptors() void fetchDescriptors()
{ {
size_t max_to_fetch = descTail() - cachePnt; size_t max_to_fetch;
if (max_to_fetch < 0)
if (descTail() >= cachePnt)
max_to_fetch = descTail() - cachePnt;
else
max_to_fetch = descLen() - cachePnt; max_to_fetch = descLen() - cachePnt;
max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() - max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() -
unusedCache.size())); unusedCache.size()));
@ -311,8 +346,9 @@ class IGbE : public PciDev
#endif #endif
cachePnt += curFetching; cachePnt += curFetching;
if (cachePnt > descLen()) assert(cachePnt <= descLen());
cachePnt -= descLen(); if (cachePnt == descLen())
cachePnt = 0;
curFetching = 0; curFetching = 0;
@ -320,7 +356,7 @@ class IGbE : public PciDev
oldCp, cachePnt); oldCp, cachePnt);
enableSm(); enableSm();
igbe->checkDrain();
} }
EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent; EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
@ -337,8 +373,8 @@ class IGbE : public PciDev
curHead += wbOut; curHead += wbOut;
wbOut = 0; wbOut = 0;
if (curHead > descLen()) if (curHead >= descLen())
curHead = 0; curHead -= descLen();
// Update the head // Update the head
updateHead(curHead); updateHead(curHead);
@ -352,6 +388,7 @@ class IGbE : public PciDev
writeback(wbAlignment); writeback(wbAlignment);
} }
intAfterWb(); intAfterWb();
igbe->checkDrain();
} }
@ -390,6 +427,63 @@ class IGbE : public PciDev
usedCache.clear(); usedCache.clear();
unusedCache.clear(); unusedCache.clear();
cachePnt = 0;
}
virtual void serialize(std::ostream &os)
{
SERIALIZE_SCALAR(cachePnt);
SERIALIZE_SCALAR(curFetching);
SERIALIZE_SCALAR(wbOut);
SERIALIZE_SCALAR(moreToWb);
SERIALIZE_SCALAR(wbAlignment);
int usedCacheSize = usedCache.size();
SERIALIZE_SCALAR(usedCacheSize);
for(int x = 0; x < usedCacheSize; x++) {
arrayParamOut(os, csprintf("usedCache_%d", x),
(uint8_t*)usedCache[x],sizeof(T));
}
int unusedCacheSize = unusedCache.size();
SERIALIZE_SCALAR(unusedCacheSize);
for(int x = 0; x < unusedCacheSize; x++) {
arrayParamOut(os, csprintf("unusedCache_%d", x),
(uint8_t*)unusedCache[x],sizeof(T));
}
}
virtual void unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(cachePnt);
UNSERIALIZE_SCALAR(curFetching);
UNSERIALIZE_SCALAR(wbOut);
UNSERIALIZE_SCALAR(moreToWb);
UNSERIALIZE_SCALAR(wbAlignment);
int usedCacheSize;
UNSERIALIZE_SCALAR(usedCacheSize);
T *temp;
for(int x = 0; x < usedCacheSize; x++) {
temp = new T;
arrayParamIn(cp, section, csprintf("usedCache_%d", x),
(uint8_t*)temp,sizeof(T));
usedCache.push_back(temp);
}
int unusedCacheSize;
UNSERIALIZE_SCALAR(unusedCacheSize);
for(int x = 0; x < unusedCacheSize; x++) {
temp = new T;
arrayParamIn(cp, section, csprintf("unusedCache_%d", x),
(uint8_t*)temp,sizeof(T));
unusedCache.push_back(temp);
}
}
virtual bool hasOutstandingEvents() {
return wbEvent.scheduled() || fetchEvent.scheduled();
} }
}; };
@ -428,6 +522,10 @@ class IGbE : public PciDev
EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent; EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
virtual bool hasOutstandingEvents();
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };
friend class RxDescCache; friend class RxDescCache;
@ -447,7 +545,6 @@ class IGbE : public PciDev
bool pktDone; bool pktDone;
bool isTcp; bool isTcp;
bool pktWaiting; bool pktWaiting;
int hLen;
public: public:
TxDescCache(IGbE *i, std::string n, int s); TxDescCache(IGbE *i, std::string n, int s);
@ -475,6 +572,11 @@ class IGbE : public PciDev
void pktComplete(); void pktComplete();
EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent; EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
virtual bool hasOutstandingEvents();
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };
friend class TxDescCache; friend class TxDescCache;
@ -513,7 +615,8 @@ class IGbE : public PciDev
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual unsigned int drain(Event *de);
virtual void resume();
}; };

View file

@ -162,7 +162,7 @@ struct TxDesc {
namespace TxdOp { namespace TxdOp {
const uint8_t TXD_CNXT = 0x0; const uint8_t TXD_CNXT = 0x0;
const uint8_t TXD_DATA = 0x0; const uint8_t TXD_DATA = 0x1;
bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); } bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); } uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
@ -220,6 +220,14 @@ struct Regs {
bool operator==(T d) { return d == _data; } bool operator==(T d) { return d == _data; }
void operator()(T d) { _data = d; } void operator()(T d) { _data = d; }
Reg() { _data = 0; } Reg() { _data = 0; }
void serialize(std::ostream &os)
{
SERIALIZE_SCALAR(_data);
}
void unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(_data);
}
}; };
struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register
@ -595,6 +603,79 @@ struct Regs {
ADD_FIELD32(smbclkout,30,1); // smb clock out ADD_FIELD32(smbclkout,30,1); // smb clock out
}; };
MANC manc; MANC manc;
};
}; // iGbReg namespace void serialize(std::ostream &os)
{
paramOut(os, "ctrl", ctrl._data);
paramOut(os, "sts", sts._data);
paramOut(os, "eecd", eecd._data);
paramOut(os, "eerd", eerd._data);
paramOut(os, "ctrl_ext", ctrl_ext._data);
paramOut(os, "mdic", mdic._data);
paramOut(os, "icr", icr._data);
SERIALIZE_SCALAR(imr);
paramOut(os, "itr", itr._data);
SERIALIZE_SCALAR(iam);
paramOut(os, "rctl", rctl._data);
paramOut(os, "fcttv", fcttv._data);
paramOut(os, "tctl", tctl._data);
paramOut(os, "pba", pba._data);
paramOut(os, "fcrtl", fcrtl._data);
paramOut(os, "fcrth", fcrth._data);
paramOut(os, "rdba", rdba._data);
paramOut(os, "rdlen", rdlen._data);
paramOut(os, "rdh", rdh._data);
paramOut(os, "rdt", rdt._data);
paramOut(os, "rdtr", rdtr._data);
paramOut(os, "rxdctl", rxdctl._data);
paramOut(os, "radv", radv._data);
paramOut(os, "rsrpd", rsrpd._data);
paramOut(os, "tdba", tdba._data);
paramOut(os, "tdlen", tdlen._data);
paramOut(os, "tdh", tdh._data);
paramOut(os, "tdt", tdt._data);
paramOut(os, "tidv", tidv._data);
paramOut(os, "txdctl", txdctl._data);
paramOut(os, "tadv", tadv._data);
paramOut(os, "rxcsum", rxcsum._data);
paramOut(os, "manc", manc._data);
}
void unserialize(Checkpoint *cp, const std::string &section)
{
paramIn(cp, section, "ctrl", ctrl._data);
paramIn(cp, section, "sts", sts._data);
paramIn(cp, section, "eecd", eecd._data);
paramIn(cp, section, "eerd", eerd._data);
paramIn(cp, section, "ctrl_ext", ctrl_ext._data);
paramIn(cp, section, "mdic", mdic._data);
paramIn(cp, section, "icr", icr._data);
UNSERIALIZE_SCALAR(imr);
paramIn(cp, section, "itr", itr._data);
UNSERIALIZE_SCALAR(iam);
paramIn(cp, section, "rctl", rctl._data);
paramIn(cp, section, "fcttv", fcttv._data);
paramIn(cp, section, "tctl", tctl._data);
paramIn(cp, section, "pba", pba._data);
paramIn(cp, section, "fcrtl", fcrtl._data);
paramIn(cp, section, "fcrth", fcrth._data);
paramIn(cp, section, "rdba", rdba._data);
paramIn(cp, section, "rdlen", rdlen._data);
paramIn(cp, section, "rdh", rdh._data);
paramIn(cp, section, "rdt", rdt._data);
paramIn(cp, section, "rdtr", rdtr._data);
paramIn(cp, section, "rxdctl", rxdctl._data);
paramIn(cp, section, "radv", radv._data);
paramIn(cp, section, "rsrpd", rsrpd._data);
paramIn(cp, section, "tdba", tdba._data);
paramIn(cp, section, "tdlen", tdlen._data);
paramIn(cp, section, "tdh", tdh._data);
paramIn(cp, section, "tdt", tdt._data);
paramIn(cp, section, "tidv", tidv._data);
paramIn(cp, section, "txdctl", txdctl._data);
paramIn(cp, section, "tadv", tadv._data);
paramIn(cp, section, "rxcsum", rxcsum._data);
paramIn(cp, section, "manc", manc._data);
}
};
} // iGbReg namespace

View file

@ -1,11 +1,7 @@
[root] [root]
type=Root type=Root
children=system children=system
checkpoint= dummy=0
clock=1000000000000
max_tick=0
output_file=cout
progress_interval=0
[system] [system]
type=System type=System

View file

@ -1,9 +1,6 @@
[root] [root]
type=Root type=Root
clock=1000000000000 dummy=0
max_tick=0
progress_interval=0
output_file=cout
[system.physmem] [system.physmem]
type=PhysicalMemory type=PhysicalMemory

View file

@ -1,18 +1,18 @@
---------- Begin Simulation Statistics ---------- ---------- Begin Simulation Statistics ----------
host_inst_rate 104057 # Simulator instruction rate (inst/s) host_inst_rate 65718 # Simulator instruction rate (inst/s)
host_mem_usage 179368 # Number of bytes of host memory used host_mem_usage 179556 # Number of bytes of host memory used
host_seconds 0.10 # Real time elapsed on the host host_seconds 0.17 # Real time elapsed on the host
host_tick_rate 103746 # Simulator tick rate (ticks/s) host_tick_rate 65601 # Simulator tick rate (ticks/s)
sim_freq 1000000000000 # Frequency of simulated ticks sim_freq 1000000000000 # Frequency of simulated ticks
sim_insts 10367 # Number of instructions simulated sim_insts 11001 # Number of instructions simulated
sim_seconds 0.000000 # Number of seconds simulated sim_seconds 0.000000 # Number of seconds simulated
sim_ticks 10366 # Number of ticks simulated sim_ticks 11000 # Number of ticks simulated
system.cpu.idle_fraction 0 # Percentage of idle cycles system.cpu.idle_fraction 0 # Percentage of idle cycles
system.cpu.not_idle_fraction 1 # Percentage of non-idle cycles system.cpu.not_idle_fraction 1 # Percentage of non-idle cycles
system.cpu.numCycles 10367 # number of cpu cycles simulated system.cpu.numCycles 11001 # number of cpu cycles simulated
system.cpu.num_insts 10367 # Number of instructions executed system.cpu.num_insts 11001 # Number of instructions executed
system.cpu.num_refs 2607 # Number of memory references system.cpu.num_refs 2760 # Number of memory references
system.cpu.workload.PROG:num_syscalls 8 # Number of system calls system.cpu.workload.PROG:num_syscalls 8 # Number of system calls
---------- End Simulation Statistics ---------- ---------- End Simulation Statistics ----------

View file

@ -7,6 +7,7 @@ CASX FAIL: Passed
CASX WORK: Passed CASX WORK: Passed
LDTX: Passed LDTX: Passed
LDTW: Passed LDTW: Passed
STTW: Passed
Done Done
M5 Simulator System M5 Simulator System
@ -15,8 +16,9 @@ The Regents of The University of Michigan
All Rights Reserved All Rights Reserved
M5 compiled Mar 6 2007 15:43:35 M5 compiled Mar 29 2007 15:29:35
M5 started Tue Mar 6 15:52:39 2007 M5 started Thu Mar 29 15:39:35 2007
M5 executing on zeep M5 executing on zeep
command line: build/SPARC_SE/m5.debug -d build/SPARC_SE/tests/debug/quick/02.insttest/sparc/linux/simple-atomic tests/run.py quick/02.insttest/sparc/linux/simple-atomic command line: build/SPARC_SE/m5.debug -d build/SPARC_SE/tests/debug/quick/02.insttest/sparc/linux/simple-atomic tests/run.py quick/02.insttest/sparc/linux/simple-atomic
Exiting @ tick 10366 because target called exit() Global frequency set at 1000000000000 ticks per second
Exiting @ tick 11000 because target called exit()