38 #include "arch/vtophys.hh"
45 #include "config/the_isa.hh"
46 #include "debug/EthernetAll.hh"
55 using namespace TheISA;
84 intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
85 cpuPendingIntr(false), intrEvent(0), interface(NULL)
90 :
Base(p), rxUnique(0), txUnique(0),
91 virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
92 rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
93 rxKickTick(0), txKickTick(0),
94 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
95 dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
96 dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
98 interface = new Interface(name() + ".int0", this);
115 .
desc(
"maximum vnic distance")
119 .
name(
name() +
".totalVnicDistance")
120 .
desc(
"total vnic distance")
124 .
desc(
"number of vnic distance measurements")
129 .
desc(
"average vnic distance")
146 if (if_name ==
"interface") {
148 panic(
"interface already connected to\n");
161 panic(
"Trying to access a vnic that doesn't exist %d > %d\n",
172 using namespace Regs;
178 uint64_t rxdone = vnic.RxDone;
181 rxdone = set_RxDone_High(rxdone,
rxFifo.
size() >
regs.RxFifoHigh);
182 rxdone = set_RxDone_NotHigh(rxdone,
rxLow);
183 regs.RxData = vnic.RxData;
184 regs.RxDone = rxdone;
185 regs.RxWait = rxdone;
188 uint64_t txdone = vnic.TxDone;
192 regs.TxData = vnic.TxData;
193 regs.TxDone = txdone;
194 regs.TxWait = txdone;
200 if (vnic != -1 &&
virtualRegs[vnic].rxPacketOffset > 0)
204 regs.RxStatus = set_RxStatus_Head(
regs.RxStatus, head);
231 panic(
"invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
236 panic(
"read %s (write only): "
237 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
240 panic(
"read %s (invalid size): "
241 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
260 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
261 info.name, cpu, index, daddr, pkt->
getAddr(), pkt->
getSize(), value);
265 if (raddr == Regs::IntrStatus)
316 panic(
"invalid register: cpu=%d, da=%#x pa=%#x size=%d",
321 panic(
"write %s (read only): "
322 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
325 if (pkt->
getSize() != info.size)
326 panic(
"write %s (invalid size): "
327 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
333 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
334 info.name, index, cpu, info.size == 4 ? pkt->
get<uint32_t>() :
348 case Regs::IntrStatus:
357 if (Regs::get_RxDone_Busy(vnic.
RxDone))
358 panic(
"receive machine busy with another request! rxState=%s",
362 vnic.
RxDone = Regs::RxDone_Busy;
366 if (Regs::get_RxData_Vaddr(pkt->
get<uint64_t>())) {
367 panic(
"vtophys not implemented in newmem");
369 Addr vaddr = Regs::get_RxData_Addr(reg64);
371 DPRINTF(EthernetPIO,
"write RxData vnic %d (rxunique %d): "
372 "vaddr=%#x, paddr=%#x\n",
373 index, vnic.
rxUnique, vaddr, paddr);
375 vnic.
RxData = Regs::set_RxData_Addr(vnic.
RxData, paddr);
378 DPRINTF(EthernetPIO,
"write RxData vnic %d (rxunique %d)\n",
383 DPRINTF(EthernetPIO,
"request new packet...appending to rxList\n");
386 DPRINTF(EthernetPIO,
"packet exists...appending to rxBusy\n");
397 if (Regs::get_TxDone_Busy(vnic.
TxDone))
398 panic(
"transmit machine busy with another request! txState=%s",
402 vnic.
TxDone = Regs::TxDone_Busy;
404 if (Regs::get_TxData_Vaddr(pkt->
get<uint64_t>())) {
405 panic(
"vtophys won't work here in newmem.\n");
407 Addr vaddr = Regs::get_TxData_Addr(reg64);
409 DPRINTF(EthernetPIO,
"write TxData vnic %d (txunique %d): "
410 "vaddr=%#x, paddr=%#x\n",
411 index, vnic.
txUnique, vaddr, paddr);
413 vnic.
TxData = Regs::set_TxData_Addr(vnic.
TxData, paddr);
416 DPRINTF(EthernetPIO,
"write TxData vnic %d (txunique %d)\n",
435 if ((interrupts & Regs::Intr_Res))
436 panic(
"Cannot set a reserved interrupt");
438 regs.IntrStatus |= interrupts;
441 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
442 interrupts,
regs.IntrStatus,
regs.IntrMask);
444 interrupts =
regs.IntrStatus &
regs.IntrMask;
451 interrupts &= ~Regs::Intr_RxHigh;
458 interrupts &= ~Regs::Intr_TxLow;
462 if ((interrupts & Regs::Intr_NoDelay) == 0)
471 if ((interrupts & Regs::Intr_Res))
472 panic(
"Cannot clear a reserved interrupt");
474 regs.IntrStatus &= ~interrupts;
477 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
478 interrupts,
regs.IntrStatus,
regs.IntrMask);
480 if (!(
regs.IntrStatus &
regs.IntrMask))
487 if (
regs.IntrMask == newmask)
490 regs.IntrMask = newmask;
493 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
496 if (
regs.IntrStatus &
regs.IntrMask)
517 DPRINTF(EthernetIntr,
"interrupts not enabled.\n",
523 DPRINTF(EthernetIntr,
"don't need to schedule event...intrTick=%d\n",
533 DPRINTF(EthernetIntr,
"going to schedule an interrupt for intrTick=%d\n",
555 "would send an interrupt now, but there's already pending\n");
560 DPRINTF(EthernetIntr,
"posting interrupt\n");
580 DPRINTF(EthernetIntr,
"clearing cchip interrupt\n");
591 uint32_t changed =
regs.Config ^ newconf;
595 regs.Config = newconf;
597 if ((changed & Regs::Config_IntEn)) {
600 if (
regs.IntrStatus &
regs.IntrMask)
607 if ((changed & Regs::Config_TxEn)) {
613 if ((changed & Regs::Config_RxEn)) {
623 if (command & Regs::Command_Intr)
626 if (command & Regs::Command_Reset)
633 using namespace Regs;
639 regs.Config |= Config_RxThread;
641 regs.Config |= Config_TxThread;
643 regs.Config |= Config_RSS;
645 regs.Config |= Config_ZeroCopy;
647 regs.Config |= Config_DelayCopy;
648 if (
params()->virtual_addr)
649 regs.Config |= Config_Vaddr;
652 panic(
"Can't delay copy and zero copy");
654 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
658 regs.ZeroCopyMark =
params()->zero_copy_threshold;
665 regs.RxFifoHigh =
params()->rx_fifo_threshold;
666 regs.TxFifoHigh =
params()->tx_fifo_high_mark;
669 if (
regs.RxMaxCopy <
regs.ZeroCopyMark)
670 panic(
"Must be able to copy at least as many bytes as the threshold");
672 if (
regs.ZeroCopySize >=
regs.ZeroCopyMark)
673 panic(
"The number of bytes to copy must be less than the threshold");
705 DPRINTF(EthernetDMA,
"end rx dma write paddr=%#x len=%d\n",
721 DPRINTF(EthernetSM,
"rxKick: rxState=%s (rxFifo.size=%d)\n",
725 DPRINTF(EthernetSM,
"rxKick: exiting, can't run till %d\n",
739 DPRINTF(EthernetSM,
"processing rxState=%s\n",
744 "processing rxState=%s for vnic %d (rxunique %d)\n",
753 for (
int i = 0;
i <
size; ++
i) {
755 bool busy = Regs::get_RxDone_Busy(vn->
RxDone);
762 status =
"busy,dirty";
771 "vnic %d %s (rxunique %d), packet %d, slack %d\n",
777 DPRINTF(EthernetSM,
"vnic %d unmapped (rxunique %d)\n",
789 panic(
"continuing vnic without packet\n");
792 "continue processing for vnic %d (rxunique %d)\n",
809 DPRINTF(EthernetSM,
"receive waiting for data. Nothing to do.\n");
814 panic(
"Not idle, but nothing to do!");
823 "processing new packet for vnic %d (rxunique %d)\n",
838 DPRINTF(Ethernet,
"ID is %d\n", ip->
id());
841 if (
cksum(ip) != 0) {
842 DPRINTF(EthernetCksum,
"Rx IP Checksum Error\n");
849 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
854 if (
cksum(tcp) != 0) {
855 DPRINTF(EthernetCksum,
"Rx TCP Checksum Error\n");
861 if (
cksum(udp) != 0) {
862 DPRINTF(EthernetCksum,
"Rx UDP Checksum Error\n");
883 if ((Regs::get_Config_ZeroCopy(
regs.Config) ||
884 Regs::get_Config_DelayCopy(
regs.Config)) &&
885 !Regs::get_RxData_NoDelay(vnic->
RxData) &&
rxLow) {
900 DPRINTF(EthernetSM,
"receive machine still copying\n");
905 vnic->
RxDone |= Regs::RxDone_Complete;
916 "rxKick: packet complete on vnic %d (rxunique %d)\n",
927 vnic->
RxDone |= Regs::RxDone_More;
931 "rxKick: packet not complete on vnic %d (rxunique %d): "
954 panic(
"Invalid rxState!");
957 DPRINTF(EthernetSM,
"entering next rxState=%s\n",
966 DPRINTF(EthernetSM,
"rx state machine exited rxState=%s\n",
975 DPRINTF(EthernetDMA,
"tx dma read paddr=%#x len=%d\n",
990 DPRINTF(Ethernet,
"nothing to transmit\n");
997 DPRINTF(Ethernet,
"Packet Transmit: failed txFifo available %d\n",
1007 DPRINTF(Ethernet,
"ID is %d\n", ip->
id());
1011 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1012 tcp->sport(), tcp->dport(), tcp->seq(),
1019 DDUMP(EthernetData, packet->data, packet->length);
1023 DPRINTF(Ethernet,
"Packet Transmit: successful txFifo Available %d\n",
1026 interrupts = Regs::Intr_TxPacket;
1028 interrupts |= Regs::Intr_TxLow;
1036 DPRINTF(EthernetSM,
"txKick: txState=%s (txFifo.size=%d)\n",
1040 DPRINTF(EthernetSM,
"txKick: exiting, can't run till %d\n",
1054 assert(Regs::get_TxDone_Busy(vnic->TxDone));
1057 txPacket = make_shared<EthPacketData>(16384);
1062 Regs::get_TxData_Len(vnic->TxData)) {
1063 DPRINTF(EthernetSM,
"transmit fifo full. Nothing to do.\n");
1075 txDmaLen = Regs::get_TxData_Len(vnic->TxData);
1083 DPRINTF(EthernetSM,
"transmit machine still copying\n");
1087 vnic->TxDone =
txDmaLen | Regs::TxDone_Complete;
1090 if ((vnic->TxData & Regs::TxData_More)) {
1098 if ((vnic->TxData & Regs::TxData_Checksum)) {
1134 panic(
"Invalid txState!");
1137 DPRINTF(EthernetSM,
"entering next txState=%s\n",
1146 DPRINTF(EthernetSM,
"tx state machine exited txState=%s\n",
1154 DPRINTF(Ethernet,
"transfer complete: txFifo empty...nothing to do\n");
1158 DPRINTF(Ethernet,
"transfer complete: data in txFifo...schedule xmit\n");
1166 if (!Regs::get_Config_Filter(
regs.Config))
1169 panic(
"receive filter not implemented\n");
1175 EthHdr *eth = packet->eth();
1176 if (eth->unicast()) {
1182 if (acceptPerfect &&
params->eaddr == eth.
dst())
1185 if (acceptArp && eth->
type() == ETH_TYPE_ARP)
1188 }
else if (eth->broadcast()) {
1190 if (acceptBroadcast)
1193 }
else if (eth->multicast()) {
1195 if (acceptMulticast)
1201 DPRINTF(Ethernet,
"rxFilter drop\n");
1202 DDUMP(EthernetData, packet->data, packet->length);
1214 DPRINTF(Ethernet,
"Receiving packet from wire, rxFifo Available is %d\n",
1218 DPRINTF(Ethernet,
"receive disabled...packet dropped\n");
1223 DPRINTF(Ethernet,
"packet filtered...dropped\n");
1232 "packet will not fit in receive buffer...packet dropped\n");
1276 Tick intrEventTick = 0;
1299 if (intrEventTick) {
1314 panic(
"can't serialize with an in flight dma request rxState=%s",
1318 panic(
"can't serialize with an in flight dma request txState=%s",
1335 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1345 paramOut(cp, reg +
".rxPacketExists", rxPacketExists);
1346 if (rxPacketExists) {
1355 paramOut(cp, reg +
".rxPacket", rxPacket);
1372 VirtualList::const_iterator
i, end;
1373 for (count = 0, i =
rxList.begin(), end =
rxList.end(); i != end; ++
i)
1375 int rxListSize =
count;
1378 for (count = 0, i =
rxBusy.begin(), end =
rxBusy.end(); i != end; ++
i)
1380 int rxBusySize =
count;
1383 for (count = 0, i =
txList.begin(), end =
txList.end(); i != end; ++
i)
1385 int txListSize =
count;
1404 bool txPacketExists =
txPacket !=
nullptr;
1406 if (txPacketExists) {
1407 txPacket->serialize(
"txPacket", cp);
1443 for (
int i = 0;
i < rxListSize; ++
i) {
1452 for (
int i = 0;
i < rxBusySize; ++
i) {
1461 for (
int i = 0;
i < txListSize; ++
i) {
1474 this->rxState = (
RxState) rxState;
1479 if (rxFifoPtr >= 0) {
1493 this->txState = (
TxState) txState;
1495 bool txPacketExists;
1498 if (txPacketExists) {
1499 txPacket = make_shared<EthPacketData>(16384);
1500 txPacket->unserialize(
"txPacket", cp);
1511 int virtualRegsSize;
1515 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1527 bool rxPacketExists;
1528 paramIn(cp, reg +
".rxPacketExists", rxPacketExists);
1529 if (rxPacketExists) {
1531 paramIn(cp, reg +
".rxPacket", rxPacket);
1536 paramIn(cp, reg +
".rxPacketOffset",
1560 SinicParams::create()
EventWrapper< Device,&Device::rxDmaDone > rxDmaEvent
const char * TxStateStrings[]
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
virtual void resetStats()
Reset statistics associated with this object.
Cycles is a wrapper class for representing cycle counts, i.e.
const Regs::Info & regInfo(Addr daddr)
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay=0)
PacketFifo::iterator rxFifoPtr
void unserialize(const std::string &base, CheckpointIn &cp)
ContextID contextId() const
Accessor function for context ID.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Dummy class to keep the Python class hierarchy in sync with the C++ object hierarchy.
void devIntrPost(uint32_t interrupts)
Interrupt management.
#define LL(N)
int64_t constant
TxState
Transmit State Machine states.
int countPacketsBefore(const_iterator i) const
void prepareRead(ContextID cpu, int index)
uint16_t cksum(const IpPtr &ptr)
void transmit()
Retransmit event.
struct Sinic::Device::@70 regs
device register file
Stats::Scalar rxIpChecksums
void cpuIntrPost(Tick when)
Stats::Scalar rxUdpChecksums
bool scheduled() const
Determine if the current event is scheduled.
#define DDUMP(x, data, count)
void regStats() override
Register statistics for this object.
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay=0)
Stats::Scalar rxTcpChecksums
void command(uint32_t command)
Stats::Scalar maxVnicDistance
Addr pciToDma(Addr pci_addr) const
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
static const int VirtualShift
PioPort pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
void serialize(CheckpointOut &cp) const override
Serialization stuff.
bool rxFilter(const EthPacketPtr &packet)
receive address filter
uint64_t & regData64(Addr daddr)
#define UNSERIALIZE_SCALAR(scalar)
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
Tick when() const
Get the time that the event is scheduled.
EtherInt * getEthPort(const std::string &if_name, int idx) override
Additional function to return the Port of a memory object.
void regStats()
Register statistics for this object.
uint64_t Tick
Tick count type.
bool regValid(Addr daddr)
void prepareIO(ContextID cpu, int index)
Stats::Scalar numVnicDistance
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Tick read(PacketPtr pkt) override
Memory Interface.
const RequestPtr req
A pointer to the original request.
Stats::Formula avgVnicDistance
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void resetStats() override
Reset statistics associated with this object.
Stats::Scalar txIpChecksums
std::shared_ptr< EthPacketData > EthPacketPtr
void rxDmaDone()
DMA parameters.
void devIntrClear(uint32_t interrupts=Regs::Intr_All)
void squash()
Squash the current event.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
bool recvPacket(EthPacketPtr packet)
device ethernet interface
Addr BARAddrs[6]
The current address mapping of the BARs.
void sendRangeChange() const
Called by the owner to send a range change.
#define SERIALIZE_SCALAR(scalar)
Stats::Scalar totalVnicDistance
Statistics.
static const int NumArgumentRegs M5_VAR_USED
bool sendPacket(EthPacketPtr packet)
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
uint32_t & regData32(Addr daddr)
void reschedule(Event &event, Tick when, bool always=false)
Stats::Scalar txUdpChecksums
Tick write(PacketPtr pkt) override
IPR read of device register.
bool cpuIntrPending() const
virtual const std::string name() const
Declaration of the Packet class.
std::ostream CheckpointOut
fifo_list::iterator iterator
void prepareWrite(ContextID cpu, int index)
void changeConfig(uint32_t newconfig)
device configuration
virtual void drainResume()
Resume execution after a successful drain.
const EthAddr & dst() const
PacketFifo::iterator rxIndex
void devIntrChangeMask(uint32_t newmask)
void schedule(Event &event, Tick when)
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
int countPacketsAfter(const_iterator i) const
RxState
Receive State Machine States.
DrainState drainState() const
Return the current drain state of an object.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
virtual void drainResume() override
Resume execution after a successful drain.
bool push(EthPacketPtr ptr)
PCIConfig config
The current config space.
static const int VirtualMask
const Params * params() const
int ContextID
Globally unique thread context ID.
void serialize(CheckpointOut &cp) const override
Serialization stuff.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
uint32_t BARSize[6]
The size of the BARs.
Stats::Scalar txTcpChecksums
const char * RxStateStrings[]
EventWrapper< Base,&Base::cpuInterrupt > IntrEvent
EventWrapper< Device,&Device::txDmaDone > txDmaEvent