41 #include "debug/EthernetAll.hh" 78 intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
79 cpuPendingIntr(false), intrEvent(0), interface(NULL)
84 :
Base(p), rxUnique(0), txUnique(0),
85 virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
86 rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
87 rxKickTick(0), txKickTick(0),
94 interface = new Interface(name() + ".int0", this);
111 .
desc(
"maximum vnic distance")
115 .
name(
name() +
".totalVnicDistance")
116 .
desc(
"total vnic distance")
120 .
desc(
"number of vnic distance measurements")
125 .
desc(
"average vnic distance")
142 if (if_name ==
"interface")
153 panic(
"Trying to access a vnic that doesn't exist %d > %d\n",
164 using namespace Regs;
170 uint64_t rxdone = vnic.
RxDone;
173 rxdone = set_RxDone_High(rxdone,
rxFifo.
size() >
regs.RxFifoHigh);
174 rxdone = set_RxDone_NotHigh(rxdone,
rxLow);
176 regs.RxDone = rxdone;
177 regs.RxWait = rxdone;
180 uint64_t txdone = vnic.
TxDone;
185 regs.TxDone = txdone;
186 regs.TxWait = txdone;
192 if (vnic != -1 &&
virtualRegs[vnic].rxPacketOffset > 0)
196 regs.RxStatus = set_RxStatus_Head(
regs.RxStatus, head);
223 panic(
"invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
228 panic(
"read %s (write only): " 229 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
232 panic(
"read %s (invalid size): " 233 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
252 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
253 info.name, cpu, index, daddr, pkt->
getAddr(), pkt->
getSize(), value);
257 if (raddr == Regs::IntrStatus)
308 panic(
"invalid register: cpu=%d, da=%#x pa=%#x size=%d",
313 panic(
"write %s (read only): " 314 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
317 if (pkt->
getSize() != info.size)
318 panic(
"write %s (invalid size): " 319 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
325 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
326 info.name, index, cpu, info.size == 4 ?
327 pkt->
getLE<uint32_t>() : pkt->
getLE<uint64_t>(),
341 case Regs::IntrStatus:
343 pkt->
getLE<uint32_t>());
351 if (Regs::get_RxDone_Busy(vnic.
RxDone))
352 panic(
"receive machine busy with another request! rxState=%s",
356 vnic.
RxDone = Regs::RxDone_Busy;
360 if (Regs::get_RxData_Vaddr(pkt->
getLE<uint64_t>())) {
361 panic(
"vtophys not implemented in newmem");
363 DPRINTF(EthernetPIO,
"write RxData vnic %d (rxunique %d)\n",
368 DPRINTF(EthernetPIO,
"request new packet...appending to rxList\n");
371 DPRINTF(EthernetPIO,
"packet exists...appending to rxBusy\n");
382 if (Regs::get_TxDone_Busy(vnic.
TxDone))
383 panic(
"transmit machine busy with another request! txState=%s",
387 vnic.
TxDone = Regs::TxDone_Busy;
389 if (Regs::get_TxData_Vaddr(pkt->
getLE<uint64_t>())) {
390 panic(
"vtophys won't work here in newmem.\n");
392 DPRINTF(EthernetPIO,
"write TxData vnic %d (txunique %d)\n",
411 if ((interrupts & Regs::Intr_Res))
412 panic(
"Cannot set a reserved interrupt");
414 regs.IntrStatus |= interrupts;
417 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
418 interrupts,
regs.IntrStatus,
regs.IntrMask);
420 interrupts =
regs.IntrStatus &
regs.IntrMask;
427 interrupts &= ~Regs::Intr_RxHigh;
434 interrupts &= ~Regs::Intr_TxLow;
438 if ((interrupts & Regs::Intr_NoDelay) == 0)
447 if ((interrupts & Regs::Intr_Res))
448 panic(
"Cannot clear a reserved interrupt");
450 regs.IntrStatus &= ~interrupts;
453 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
454 interrupts,
regs.IntrStatus,
regs.IntrMask);
456 if (!(
regs.IntrStatus &
regs.IntrMask))
463 if (
regs.IntrMask == newmask)
466 regs.IntrMask = newmask;
469 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
472 if (
regs.IntrStatus &
regs.IntrMask)
493 DPRINTF(EthernetIntr,
"interrupts not enabled.\n",
499 DPRINTF(EthernetIntr,
"don't need to schedule event...intrTick=%d\n",
509 DPRINTF(EthernetIntr,
"going to schedule an interrupt for intrTick=%d\n",
533 "would send an interrupt now, but there's already pending\n");
538 DPRINTF(EthernetIntr,
"posting interrupt\n");
558 DPRINTF(EthernetIntr,
"clearing cchip interrupt\n");
569 uint32_t changed =
regs.Config ^ newconf;
573 regs.Config = newconf;
575 if ((changed & Regs::Config_IntEn)) {
578 if (
regs.IntrStatus &
regs.IntrMask)
585 if ((changed & Regs::Config_TxEn)) {
591 if ((changed & Regs::Config_RxEn)) {
601 if (command & Regs::Command_Intr)
604 if (command & Regs::Command_Reset)
611 using namespace Regs;
617 regs.Config |= Config_RxThread;
619 regs.Config |= Config_TxThread;
621 regs.Config |= Config_RSS;
623 regs.Config |= Config_ZeroCopy;
625 regs.Config |= Config_DelayCopy;
626 if (
params()->virtual_addr)
627 regs.Config |= Config_Vaddr;
630 panic(
"Can't delay copy and zero copy");
632 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
636 regs.ZeroCopyMark =
params()->zero_copy_threshold;
643 regs.RxFifoHigh =
params()->rx_fifo_threshold;
644 regs.TxFifoHigh =
params()->tx_fifo_high_mark;
647 if (
regs.RxMaxCopy <
regs.ZeroCopyMark)
648 panic(
"Must be able to copy at least as many bytes as the threshold");
650 if (
regs.ZeroCopySize >=
regs.ZeroCopyMark)
651 panic(
"The number of bytes to copy must be less than the threshold");
674 for (
int i = 0;
i < size; ++
i)
683 DPRINTF(EthernetDMA,
"end rx dma write paddr=%#x len=%d\n",
699 DPRINTF(EthernetSM,
"rxKick: rxState=%s (rxFifo.size=%d)\n",
703 DPRINTF(EthernetSM,
"rxKick: exiting, can't run till %d\n",
715 panic(
"no active vnic while in state %s", RxStateStrings[rxState]);
717 DPRINTF(EthernetSM,
"processing rxState=%s\n",
718 RxStateStrings[rxState]);
722 "processing rxState=%s for vnic %d (rxunique %d)\n",
731 for (
int i = 0;
i < size; ++
i) {
733 bool busy = Regs::get_RxDone_Busy(vn->
RxDone);
740 status =
"busy,dirty";
749 "vnic %d %s (rxunique %d), packet %d, slack %d\n",
755 DPRINTF(EthernetSM,
"vnic %d unmapped (rxunique %d)\n",
767 panic(
"continuing vnic without packet\n");
770 "continue processing for vnic %d (rxunique %d)\n",
787 DPRINTF(EthernetSM,
"receive waiting for data. Nothing to do.\n");
792 panic(
"Not idle, but nothing to do!");
801 "processing new packet for vnic %d (rxunique %d)\n",
816 DPRINTF(Ethernet,
"ID is %d\n", ip->
id());
819 if (
cksum(ip) != 0) {
820 DPRINTF(EthernetCksum,
"Rx IP Checksum Error\n");
827 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
832 if (
cksum(tcp) != 0) {
833 DPRINTF(EthernetCksum,
"Rx TCP Checksum Error\n");
839 if (
cksum(udp) != 0) {
840 DPRINTF(EthernetCksum,
"Rx UDP Checksum Error\n");
861 if ((Regs::get_Config_ZeroCopy(
regs.Config) ||
862 Regs::get_Config_DelayCopy(
regs.Config)) &&
863 !Regs::get_RxData_NoDelay(vnic->
RxData) &&
rxLow) {
878 DPRINTF(EthernetSM,
"receive machine still copying\n");
883 vnic->
RxDone |= Regs::RxDone_Complete;
894 "rxKick: packet complete on vnic %d (rxunique %d)\n",
905 vnic->
RxDone |= Regs::RxDone_More;
909 "rxKick: packet not complete on vnic %d (rxunique %d): " 932 panic(
"Invalid rxState!");
935 DPRINTF(EthernetSM,
"entering next rxState=%s\n",
936 RxStateStrings[rxState]);
944 DPRINTF(EthernetSM,
"rx state machine exited rxState=%s\n",
945 RxStateStrings[rxState]);
953 DPRINTF(EthernetDMA,
"tx dma read paddr=%#x len=%d\n",
968 DPRINTF(Ethernet,
"nothing to transmit\n");
975 DPRINTF(Ethernet,
"Packet Transmit: failed txFifo available %d\n",
985 DPRINTF(Ethernet,
"ID is %d\n", ip->
id());
989 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
990 tcp->sport(), tcp->dport(), tcp->seq(),
997 DDUMP(EthernetData, packet->data, packet->length);
1001 DPRINTF(Ethernet,
"Packet Transmit: successful txFifo Available %d\n",
1004 interrupts = Regs::Intr_TxPacket;
1006 interrupts |= Regs::Intr_TxLow;
1014 DPRINTF(EthernetSM,
"txKick: txState=%s (txFifo.size=%d)\n",
1018 DPRINTF(EthernetSM,
"txKick: exiting, can't run till %d\n",
1032 assert(Regs::get_TxDone_Busy(vnic->TxDone));
1035 txPacket = make_shared<EthPacketData>(16384);
1040 Regs::get_TxData_Len(vnic->TxData)) {
1041 DPRINTF(EthernetSM,
"transmit fifo full. Nothing to do.\n");
1053 txDmaLen = Regs::get_TxData_Len(vnic->TxData);
1061 DPRINTF(EthernetSM,
"transmit machine still copying\n");
1065 vnic->TxDone =
txDmaLen | Regs::TxDone_Complete;
1068 if ((vnic->TxData & Regs::TxData_More)) {
1076 if ((vnic->TxData & Regs::TxData_Checksum)) {
1112 panic(
"Invalid txState!");
1115 DPRINTF(EthernetSM,
"entering next txState=%s\n",
1116 TxStateStrings[txState]);
1124 DPRINTF(EthernetSM,
"tx state machine exited txState=%s\n",
1125 TxStateStrings[txState]);
1132 DPRINTF(Ethernet,
"transfer complete: txFifo empty...nothing to do\n");
1136 DPRINTF(Ethernet,
"transfer complete: data in txFifo...schedule xmit\n");
1144 if (!Regs::get_Config_Filter(
regs.Config))
1147 panic(
"receive filter not implemented\n");
1158 DPRINTF(Ethernet,
"Receiving packet from wire, rxFifo Available is %d\n",
1162 DPRINTF(Ethernet,
"receive disabled...packet dropped\n");
1167 DPRINTF(Ethernet,
"packet filtered...dropped\n");
1176 "packet will not fit in receive buffer...packet dropped\n");
1220 Tick intrEventTick = 0;
1243 if (intrEventTick) {
1259 panic(
"can't serialize with an in flight dma request rxState=%s",
1263 panic(
"can't serialize with an in flight dma request txState=%s",
1280 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1290 paramOut(cp, reg +
".rxPacketExists", rxPacketExists);
1291 if (rxPacketExists) {
1300 paramOut(cp, reg +
".rxPacket", rxPacket);
1317 VirtualList::const_iterator
i, end;
1318 for (count = 0, i =
rxList.begin(), end =
rxList.end(); i != end; ++
i)
1320 int rxListSize =
count;
1323 for (count = 0, i =
rxBusy.begin(), end =
rxBusy.end(); i != end; ++
i)
1325 int rxBusySize =
count;
1328 for (count = 0, i =
txList.begin(), end =
txList.end(); i != end; ++
i)
1330 int txListSize =
count;
1349 bool txPacketExists =
txPacket !=
nullptr;
1351 if (txPacketExists) {
1352 txPacket->serialize(
"txPacket", cp);
1388 for (
int i = 0;
i < rxListSize; ++
i) {
1397 for (
int i = 0;
i < rxBusySize; ++
i) {
1406 for (
int i = 0;
i < txListSize; ++
i) {
1419 this->rxState = (
RxState) rxState;
1424 if (rxFifoPtr >= 0) {
1438 this->txState = (
TxState) txState;
1440 bool txPacketExists;
1443 if (txPacketExists) {
1444 txPacket = make_shared<EthPacketData>(16384);
1445 txPacket->unserialize(
"txPacket", cp);
1456 int virtualRegsSize;
1460 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1472 bool rxPacketExists;
1473 paramIn(cp, reg +
".rxPacketExists", rxPacketExists);
1474 if (rxPacketExists) {
1476 paramIn(cp, reg +
".rxPacket", rxPacket);
1481 paramIn(cp, reg +
".rxPacketOffset",
1505 SinicParams::create()
#define panic(...)
This implements a cprintf based panic() function.
Ports are used to interface objects to each other.
const char * TxStateStrings[]
void sendRangeChange() const
Called by the owner to send a range change.
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.
int countPacketsBefore(const_iterator i) const
PacketFifo::iterator rxFifoPtr
Addr pciToDma(Addr pci_addr) const
void unserialize(const std::string &base, CheckpointIn &cp)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Tick when() const
Get the time that the event is scheduled.
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
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
EventFunctionWrapper txEvent
TxState
Transmit State Machine states.
void prepareRead(ContextID cpu, int index)
uint16_t cksum(const IpPtr &ptr)
void transmit()
Retransmit event.
Stats::Scalar rxIpChecksums
void cpuIntrPost(Tick when)
Stats::Scalar rxUdpChecksums
DrainState drainState() const
Return the current drain state of an object.
#define DDUMP(x, data, count)
const Params * params() const
void regStats() override
Callback to set stat parameters.
EventFunctionWrapper rxDmaEvent
Overload hash function for BasicBlockRange type.
Stats::Scalar rxTcpChecksums
void command(uint32_t command)
Stats::Scalar maxVnicDistance
void setLE(T v)
Set the value in the data pointer to v as little endian.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
static const int VirtualShift
struct Sinic::Device::@94 regs
device register file
EventFunctionWrapper * intrEvent
RequestPtr req
A pointer to the original request.
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 curTick()
The current simulated tick.
std::string csprintf(const char *format, const Args &...args)
bool scheduled() const
Determine if the current event is scheduled.
void regStats()
Callback to set stat parameters.
uint64_t Tick
Tick count type.
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
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.
virtual void resetStats()
Callback to reset stats.
Stats::Formula avgVnicDistance
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void resetStats() override
Callback to reset stats.
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.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
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.
virtual const std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
bool recvPacket(EthPacketPtr packet)
device ethernet interface
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...
Addr BARAddrs[6]
The current address mapping of the BARs.
bool cpuIntrPending() const
#define SERIALIZE_SCALAR(scalar)
Stats::Scalar totalVnicDistance
Statistics.
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.
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
int countPacketsAfter(const_iterator i) const
virtual void drainResume()
Resume execution after a successful drain.
PacketFifo::iterator rxIndex
void devIntrChangeMask(uint32_t newmask)
void schedule(Event &event, Tick when)
EventFunctionWrapper txDmaEvent
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
RxState
Receive State Machine States.
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
virtual void drainResume() override
Resume execution after a successful drain.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
static const int NumArgumentRegs M5_VAR_USED
bool push(EthPacketPtr ptr)
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
PCIConfig config
The current config space.
static const int VirtualMask
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[]