a packet to exist in multiple FIFOs if desired.
EthPacketData::serialize(const string &base, ostream &os)
{
paramOut(os, base + ".length", length);
- paramOut(os, base + ".slack", slack);
arrayParamOut(os, base + ".data", data, length);
}
const string §ion)
{
paramIn(cp, section, base + ".length", length);
- paramIn(cp, section, base + ".slack", slack);
if (length)
arrayParamIn(cp, section, base + ".data", data, length);
}
*/
int length;
- /*
- * Extra space taken up by the packet in whatever data structure
- * it is in.
- *
- * NOTE: This can only be use by *one* data structure at a time!
- */
- int slack;
-
public:
- EthPacketData() : data(NULL), length(0), slack(0)
+ EthPacketData()
+ : data(NULL), length(0)
{ }
explicit EthPacketData(size_t size)
- : data(new uint8_t[size]), length(0), slack(0)
+ : data(new uint8_t[size]), length(0)
{ }
- EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
- : data(d.release()), length(l), slack(s)
+ EthPacketData(std::auto_ptr<uint8_t> d, int l)
+ : data(d.release()), length(l)
{ }
~EthPacketData() { if (data) delete [] data; }
if (offset + len >= size())
return false;
- list<EthPacketPtr>::iterator p = fifo.begin();
- list<EthPacketPtr>::iterator end = fifo.end();
+ iterator i = fifo.begin();
+ iterator end = fifo.end();
while (len > 0) {
- while (offset >= (*p)->length) {
- offset -= (*p)->length;
- ++p;
+ EthPacketPtr &pkt = i->packet;
+ while (offset >= pkt->length) {
+ offset -= pkt->length;
+ ++i;
}
- if (p == end)
+ if (i == end)
panic("invalid fifo");
- int size = min((*p)->length - offset, len);
- memcpy(data, (*p)->data, size);
+ int size = min(pkt->length - offset, len);
+ memcpy(data, pkt->data, size);
offset = 0;
len -= size;
data += size;
- ++p;
+ ++i;
}
return true;
}
+void
+PacketFifoEntry::serialize(const string &base, ostream &os)
+{
+ packet->serialize(base + ".packet", os);
+ paramOut(os, base + ".slack", slack);
+ paramOut(os, base + ".number", number);
+ paramOut(os, base + ".priv", priv);
+}
+
+void
+PacketFifoEntry::unserialize(const string &base, Checkpoint *cp,
+ const string §ion)
+{
+ packet = new EthPacketData(16384);
+ packet->unserialize(base + ".packet", cp, section);
+ paramIn(cp, section, base + ".slack", slack);
+ paramIn(cp, section, base + ".number", number);
+ paramIn(cp, section, base + ".priv", priv);
+}
+
void
PacketFifo::serialize(const string &base, ostream &os)
{
paramOut(os, base + ".packets", fifo.size());
int i = 0;
- list<EthPacketPtr>::iterator p = fifo.begin();
- list<EthPacketPtr>::iterator end = fifo.end();
- while (p != end) {
- (*p)->serialize(csprintf("%s.packet%d", base, i), os);
- ++p;
+ iterator entry = fifo.begin();
+ iterator end = fifo.end();
+ while (entry != end) {
+ entry->serialize(csprintf("%s.entry%d", base, i), os);
+ ++entry;
++i;
}
}
fifo.clear();
for (int i = 0; i < fifosize; ++i) {
- EthPacketPtr p = new EthPacketData(16384);
- p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
- fifo.push_back(p);
+ PacketFifoEntry entry;
+ entry.unserialize(csprintf("%s.entry%d", base, i), cp, section);
+ fifo.push_back(entry);
}
}
#include "sim/serialize.hh"
class Checkpoint;
+
+struct PacketFifoEntry
+{
+ EthPacketPtr packet;
+ uint64_t number;
+ int slack;
+ int priv;
+
+ PacketFifoEntry()
+ {
+ clear();
+ }
+
+ PacketFifoEntry(const PacketFifoEntry &s)
+ : packet(s.packet), number(s.number), slack(s.slack), priv(s.priv)
+ {
+ }
+
+ PacketFifoEntry(EthPacketPtr p, uint64_t n)
+ : packet(p), number(n), slack(0), priv(-1)
+ {
+ }
+
+ void clear()
+ {
+ packet = NULL;
+ number = 0;
+ slack = 0;
+ priv = -1;
+ }
+
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string §ion);
+};
+
class PacketFifo
{
public:
- typedef std::list<EthPacketPtr> fifo_list;
+
+ typedef std::list<PacketFifoEntry> fifo_list;
typedef fifo_list::iterator iterator;
protected:
- std::list<EthPacketPtr> fifo;
+ std::list<PacketFifoEntry> fifo;
+ uint64_t _counter;
int _maxsize;
int _size;
int _reserved;
public:
- explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
+ explicit PacketFifo(int max)
+ : _counter(0), _maxsize(max), _size(0), _reserved(0) {}
virtual ~PacketFifo() {}
int packets() const { return fifo.size(); }
iterator begin() { return fifo.begin(); }
iterator end() { return fifo.end(); }
- EthPacketPtr front() { return fifo.front(); }
+ EthPacketPtr front() { return fifo.begin()->packet; }
bool push(EthPacketPtr ptr)
{
assert(ptr->length);
assert(_reserved <= ptr->length);
- assert(ptr->slack == 0);
if (avail() < ptr->length - _reserved)
return false;
_size += ptr->length;
- fifo.push_back(ptr);
+
+ PacketFifoEntry entry;
+ entry.packet = ptr;
+ entry.number = _counter++;
+ fifo.push_back(entry);
_reserved = 0;
return true;
}
if (empty())
return;
- EthPacketPtr &packet = fifo.front();
- _size -= packet->length;
- _size -= packet->slack;
- packet->slack = 0;
- packet = NULL;
+ iterator entry = fifo.begin();
+ _size -= entry->packet->length;
+ _size -= entry->slack;
+ entry->packet = NULL;
fifo.pop_front();
}
void clear()
{
for (iterator i = begin(); i != end(); ++i)
- (*i)->slack = 0;
+ i->clear();
fifo.clear();
_size = 0;
_reserved = 0;
void remove(iterator i)
{
- EthPacketPtr &packet = *i;
if (i != fifo.begin()) {
iterator prev = i;
--prev;
assert(prev != fifo.end());
- (*prev)->slack += packet->length;
+ prev->slack += i->packet->length;
+ prev->slack += i->slack;
} else {
- _size -= packet->length;
- _size -= packet->slack;
+ _size -= i->packet->length;
+ _size -= i->slack;
}
- packet->slack = 0;
- packet = NULL;
+ i->clear();
fifo.erase(i);
}
bool copyout(void *dest, int offset, int len);
- int countPacketsBefore(iterator end)
+ int countPacketsBefore(iterator i)
{
- iterator i = fifo.begin();
- int count = 0;
-
- while (i != end) {
- ++count;
- ++i;
- }
-
- return count;
+ if (i == fifo.end())
+ return 0;
+ return i->number - fifo.begin()->number;
}
int countPacketsAfter(iterator i)
{
iterator end = fifo.end();
- int count = 0;
+ if (i == end)
+ return 0;
+ return (--end)->number - i->number;
+ }
- while (i != end) {
- ++count;
- ++i;
- }
+ void check()
+ {
+ int total = 0;
+ for (iterator i = begin(); i != end(); ++i)
+ total += i->packet->length + i->slack;
- return count;
+ if (total != _size)
+ panic("total (%d) is not == to size (%d)\n", total, _size);
}
-
/**
* Serialization stuff
*/
// Grab a new packet from the fifo.
vnic->rxPacket = rxFifoPtr++;
vnic->rxPacketOffset = 0;
- vnic->rxPacketBytes = (*vnic->rxPacket)->length;
+ vnic->rxPacketBytes = vnic->rxPacket->packet->length;
assert(vnic->rxPacketBytes);
vnic->rxDoneData = 0;
/* scope for variables */ {
- IpPtr ip(*vnic->rxPacket);
+ IpPtr ip(vnic->rxPacket->packet);
if (ip) {
DPRINTF(Ethernet, "ID is %d\n", ip->id());
vnic->rxDoneData |= Regs::RxDone_IpPacket;
Regs::get_RxData_Addr(vnic->RxData));
rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData),
vnic->rxPacketBytes);
- rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
+ rxDmaData = vnic->rxPacket->packet->data + vnic->rxPacketOffset;
rxState = rxCopy;
if (rxDmaAddr == 1LL) {
rxState = rxCopyDone;