Go to the documentation of this file.
39 #include "debug/EthernetAll.hh"
49 using namespace networking;
79 intrDelay(
p.intr_delay), intrTick(0), cpuIntrEnable(false),
80 cpuPendingIntr(false), intrEvent(0), interface(NULL)
85 :
Base(
p), rxUnique(0), txUnique(0),
86 virtualRegs(
p.virtual_count < 1 ? 1 :
p.virtual_count),
87 rxFifo(
p.rx_fifo_size), txFifo(
p.tx_fifo_size),
88 rxKickTick(0), txKickTick(0),
90 rxDmaEvent([
this]{ rxDmaDone(); },
name()),
91 txDmaEvent([
this]{ txDmaDone(); },
name()),
92 dmaReadDelay(
p.dma_read_delay), dmaReadFactor(
p.dma_read_factor),
93 dmaWriteDelay(
p.dma_write_delay), dmaWriteFactor(
p.dma_write_factor),
94 sinicDeviceStats(
this)
96 interface = new Interface(
name() + ".int0", this);
104 : statistics::
Group(parent,
"SinicDevice"),
106 "Total vnic distance"),
108 "Number of vnic distance measurements"),
110 "Maximum vnic distance"),
111 ADD_STAT(avgVnicDistance, statistics::units::Rate<
112 statistics::units::
Count, statistics::units::
Count>::get(),
113 "Average vnic distance", totalVnicDistance / numVnicDistance),
129 if (if_name ==
"interface")
140 panic(
"Trying to access a vnic that doesn't exist %d > %d\n",
151 using namespace registers;
157 uint64_t rxdone = vnic.
RxDone;
160 rxdone = set_RxDone_High(rxdone,
rxFifo.
size() >
regs.RxFifoHigh);
161 rxdone = set_RxDone_NotHigh(rxdone,
rxLow);
163 regs.RxDone = rxdone;
164 regs.RxWait = rxdone;
167 uint64_t txdone = vnic.
TxDone;
172 regs.TxDone = txdone;
173 regs.TxWait = txdone;
179 if (vnic != -1 &&
virtualRegs[vnic].rxPacketOffset > 0)
183 regs.RxStatus = set_RxStatus_Head(
regs.RxStatus, head);
204 assert(
BARs[0]->range().contains(daddr));
205 daddr -=
BARs[0]->addr();
212 panic(
"invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
218 panic(
"read %s (write only): "
219 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
224 panic(
"read %s (invalid size): "
225 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
231 [[maybe_unused]] uint64_t value = 0;
245 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
250 if (raddr == registers::IntrStatus)
295 assert(
BARs[0]->range().contains(daddr));
296 daddr -=
BARs[0]->addr();
303 panic(
"invalid register: cpu=%d, da=%#x pa=%#x size=%d",
308 panic(
"write %s (read only): "
309 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
313 panic(
"write %s (invalid size): "
314 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
320 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
322 pkt->
getLE<uint32_t>() : pkt->
getLE<uint64_t>(),
332 case registers::Command:
336 case registers::IntrStatus:
338 pkt->
getLE<uint32_t>());
341 case registers::IntrMask:
345 case registers::RxData:
346 if (registers::get_RxDone_Busy(vnic.
RxDone))
347 panic(
"receive machine busy with another request! rxState=%s",
351 vnic.
RxDone = registers::RxDone_Busy;
355 if (registers::get_RxData_Vaddr(pkt->
getLE<uint64_t>())) {
356 panic(
"vtophys not implemented in newmem");
358 DPRINTF(EthernetPIO,
"write RxData vnic %d (rxunique %d)\n",
363 DPRINTF(EthernetPIO,
"request new packet...appending to rxList\n");
366 DPRINTF(EthernetPIO,
"packet exists...appending to rxBusy\n");
376 case registers::TxData:
377 if (registers::get_TxDone_Busy(vnic.
TxDone))
378 panic(
"transmit machine busy with another request! txState=%s",
382 vnic.
TxDone = registers::TxDone_Busy;
384 if (registers::get_TxData_Vaddr(pkt->
getLE<uint64_t>())) {
385 panic(
"vtophys won't work here in newmem.\n");
387 DPRINTF(EthernetPIO,
"write TxData vnic %d (txunique %d)\n",
406 if ((interrupts & registers::Intr_Res))
407 panic(
"Cannot set a reserved interrupt");
409 regs.IntrStatus |= interrupts;
412 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
413 interrupts,
regs.IntrStatus,
regs.IntrMask);
415 interrupts =
regs.IntrStatus &
regs.IntrMask;
422 interrupts &= ~registers::Intr_RxHigh;
429 interrupts &= ~registers::Intr_TxLow;
433 if ((interrupts & registers::Intr_NoDelay) == 0)
442 if ((interrupts & registers::Intr_Res))
443 panic(
"Cannot clear a reserved interrupt");
445 regs.IntrStatus &= ~interrupts;
448 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
449 interrupts,
regs.IntrStatus,
regs.IntrMask);
451 if (!(
regs.IntrStatus &
regs.IntrMask))
458 if (
regs.IntrMask == newmask)
461 regs.IntrMask = newmask;
464 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
467 if (
regs.IntrStatus &
regs.IntrMask)
488 DPRINTF(EthernetIntr,
"interrupts not enabled.\n",
494 DPRINTF(EthernetIntr,
"don't need to schedule event...intrTick=%d\n",
504 DPRINTF(EthernetIntr,
"going to schedule an interrupt for intrTick=%d\n",
528 "would send an interrupt now, but there's already pending\n");
533 DPRINTF(EthernetIntr,
"posting interrupt\n");
553 DPRINTF(EthernetIntr,
"clearing cchip interrupt\n");
564 uint32_t changed =
regs.Config ^ newconf;
568 regs.Config = newconf;
570 if ((changed & registers::Config_IntEn)) {
573 if (
regs.IntrStatus &
regs.IntrMask)
580 if ((changed & registers::Config_TxEn)) {
586 if ((changed & registers::Config_RxEn)) {
596 if (
command & registers::Command_Intr)
599 if (
command & registers::Command_Reset)
606 using namespace registers;
612 regs.Config |= Config_RxThread;
614 regs.Config |= Config_TxThread;
616 regs.Config |= Config_RSS;
618 regs.Config |= Config_ZeroCopy;
620 regs.Config |= Config_DelayCopy;
621 if (
params().virtual_addr)
622 regs.Config |= Config_Vaddr;
625 panic(
"Can't delay copy and zero copy");
627 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
631 regs.ZeroCopyMark =
params().zero_copy_threshold;
642 if (
regs.RxMaxCopy <
regs.ZeroCopyMark)
643 panic(
"Must be able to copy at least as many bytes as the threshold");
645 if (
regs.ZeroCopySize >=
regs.ZeroCopyMark)
646 panic(
"The number of bytes to copy must be less than the threshold");
669 for (
int i = 0;
i < size; ++
i)
678 DPRINTF(EthernetDMA,
"end rx dma write paddr=%#x len=%d\n",
694 DPRINTF(EthernetSM,
"rxKick: rxState=%s (rxFifo.size=%d)\n",
698 DPRINTF(EthernetSM,
"rxKick: exiting, can't run till %d\n",
712 DPRINTF(EthernetSM,
"processing rxState=%s\n",
717 "processing rxState=%s for vnic %d (rxunique %d)\n",
723 if (debug::EthernetSM) {
726 for (
int i = 0;
i < size; ++
i) {
728 bool busy = registers::get_RxDone_Busy(vn->
RxDone);
744 "vnic %d %s (rxunique %d), packet %d, slack %d\n",
750 DPRINTF(EthernetSM,
"vnic %d unmapped (rxunique %d)\n",
762 panic(
"continuing vnic without packet\n");
765 "continue processing for vnic %d (rxunique %d)\n",
782 DPRINTF(EthernetSM,
"receive waiting for data. Nothing to do.\n");
787 panic(
"Not idle, but nothing to do!");
796 "processing new packet for vnic %d (rxunique %d)\n",
811 DPRINTF(Ethernet,
"ID is %d\n",
ip->id());
812 vnic->
rxDoneData |= registers::RxDone_IpPacket;
815 DPRINTF(EthernetCksum,
"Rx IP Checksum Error\n");
816 vnic->
rxDoneData |= registers::RxDone_IpError;
822 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
825 vnic->
rxDoneData |= registers::RxDone_TcpPacket;
828 DPRINTF(EthernetCksum,
"Rx TCP Checksum Error\n");
829 vnic->
rxDoneData |= registers::RxDone_TcpError;
832 vnic->
rxDoneData |= registers::RxDone_UdpPacket;
834 if (
cksum(udp) != 0) {
835 DPRINTF(EthernetCksum,
"Rx UDP Checksum Error\n");
836 vnic->
rxDoneData |= registers::RxDone_UdpError;
849 rxDmaLen = std::min<unsigned>(registers::get_RxData_Len(vnic->
RxData),
856 if ((registers::get_Config_ZeroCopy(
regs.Config) ||
857 registers::get_Config_DelayCopy(
regs.Config)) &&
858 !registers::get_RxData_NoDelay(vnic->
RxData) &&
rxLow) {
873 DPRINTF(EthernetSM,
"receive machine still copying\n");
878 vnic->
RxDone |= registers::RxDone_Complete;
890 "rxKick: packet complete on vnic %d (rxunique %d)\n",
901 vnic->
RxDone |= registers::RxDone_More;
902 vnic->
RxDone = registers::set_RxDone_CopyLen(vnic->
RxDone,
905 "rxKick: packet not complete on vnic %d (rxunique %d): "
928 panic(
"Invalid rxState!");
931 DPRINTF(EthernetSM,
"entering next rxState=%s\n",
940 DPRINTF(EthernetSM,
"rx state machine exited rxState=%s\n",
949 DPRINTF(EthernetDMA,
"tx dma read paddr=%#x len=%d\n",
964 DPRINTF(Ethernet,
"nothing to transmit\n");
971 DPRINTF(Ethernet,
"Packet Transmit: failed txFifo available %d\n",
978 if (debug::Ethernet) {
981 DPRINTF(Ethernet,
"ID is %d\n",
ip->id());
985 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
993 DDUMP(EthernetData, packet->data, packet->length);
997 DPRINTF(Ethernet,
"Packet Transmit: successful txFifo Available %d\n",
1000 interrupts = registers::Intr_TxPacket;
1002 interrupts |= registers::Intr_TxLow;
1010 DPRINTF(EthernetSM,
"txKick: txState=%s (txFifo.size=%d)\n",
1014 DPRINTF(EthernetSM,
"txKick: exiting, can't run till %d\n",
1028 assert(registers::get_TxDone_Busy(vnic->
TxDone));
1031 txPacket = std::make_shared<EthPacketData>(16384);
1036 registers::get_TxData_Len(vnic->
TxData)) {
1037 DPRINTF(EthernetSM,
"transmit fifo full. Nothing to do.\n");
1057 DPRINTF(EthernetSM,
"transmit machine still copying\n");
1064 if ((vnic->
TxData & registers::TxData_More)) {
1072 if ((vnic->
TxData & registers::TxData_Checksum)) {
1108 panic(
"Invalid txState!");
1111 DPRINTF(EthernetSM,
"entering next txState=%s\n",
1120 DPRINTF(EthernetSM,
"tx state machine exited txState=%s\n",
1128 DPRINTF(Ethernet,
"transfer complete: txFifo empty...nothing to do\n");
1132 DPRINTF(Ethernet,
"transfer complete: data in txFifo...schedule xmit\n");
1140 if (!registers::get_Config_Filter(
regs.Config))
1143 panic(
"receive filter not implemented\n");
1154 DPRINTF(Ethernet,
"Receiving packet from wire, rxFifo Available is %d\n",
1158 DPRINTF(Ethernet,
"receive disabled...packet dropped\n");
1163 DPRINTF(Ethernet,
"packet filtered...dropped\n");
1172 "packet will not fit in receive buffer...packet dropped\n");
1216 Tick intrEventTick = 0;
1239 if (intrEventTick) {
1255 panic(
"can't serialize with an in flight dma request rxState=%s",
1259 panic(
"can't serialize with an in flight dma request txState=%s",
1276 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1286 paramOut(cp,
reg +
".rxPacketExists", rxPacketExists);
1287 if (rxPacketExists) {
1313 VirtualList::const_iterator
i, end;
1316 int rxListSize =
count;
1321 int rxBusySize =
count;
1326 int txListSize =
count;
1345 bool txPacketExists =
txPacket !=
nullptr;
1347 if (txPacketExists) {
1348 txPacket->serialize(
"txPacket", cp);
1384 for (
int i = 0;
i < rxListSize; ++
i) {
1393 for (
int i = 0;
i < rxBusySize; ++
i) {
1402 for (
int i = 0;
i < txListSize; ++
i) {
1436 bool txPacketExists;
1439 if (txPacketExists) {
1440 txPacket = std::make_shared<EthPacketData>(16384);
1441 txPacket->unserialize(
"txPacket", cp);
1452 int virtualRegsSize;
1456 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1468 bool rxPacketExists;
1469 paramIn(cp,
reg +
".rxPacketExists", rxPacketExists);
1470 if (rxPacketExists) {
Tick curTick()
The universal simulation clock.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Dummy class to keep the Python class hierarchy in sync with the C++ object hierarchy.
Tick when() const
Get the time that the event is scheduled.
EventFunctionWrapper txEvent
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void cpuIntrPost(Tick when)
const char * TxStateStrings[]
PCIConfig config
The current config space.
bool recvPacket(EthPacketPtr packet)
device ethernet interface
#define UNSERIALIZE_SCALAR(scalar)
void changeConfig(uint32_t newconfig)
device configuration
DrainState drainState() const
Return the current drain state of an object.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void serialize(CheckpointOut &cp) const override
Serialization stuff.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
uint16_t cksum(const IpPtr &ptr)
DeviceStats(statistics::Group *parent)
RequestPtr req
A pointer to the original request.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
bool sendPacket(EthPacketPtr packet)
void resetStats() override
Callback to reset stats.
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
void schedule(Event &event, Tick when)
std::string csprintf(const char *format, const Args &...args)
EventFunctionWrapper txDmaEvent
statistics::Scalar txUdpChecksums
bool regValid(Addr daddr)
virtual void resetStats()
Callback to reset stats.
void devIntrClear(uint32_t interrupts=registers::Intr_All)
statistics::Scalar numVnicDistance
const char * RxStateStrings[]
statistics::Scalar txPackets
Cycles is a wrapper class for representing cycle counts, i.e.
void unserialize(const std::string &base, CheckpointIn &cp)
uint32_t & regData32(Addr daddr)
statistics::Scalar txTcpChecksums
bool rxFilter(const EthPacketPtr &packet)
receive address filter
bool cpuIntrPending() const
PacketFifo::iterator rxIndex
void prepareIO(ContextID cpu, int index)
TxState
Transmit State Machine states.
virtual void drainResume() override
Resume execution after a successful drain.
virtual std::string name() const
std::shared_ptr< EthPacketData > EthPacketPtr
const Params & params() const
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
RxState
Receive State Machine States.
gem5::sinic::Device::DeviceStats sinicDeviceStats
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
uint64_t Tick
Tick count type.
statistics::Scalar rxIpChecksums
std::array< PciBar *, 6 > BARs
statistics::Scalar maxVnicDistance
void reschedule(Event &event, Tick when, bool always=false)
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
statistics::Scalar rxUdpChecksums
void rxDmaDone()
DMA parameters.
bool push(EthPacketPtr ptr)
struct gem5::sinic::Device::@337 regs
device register file
statistics::Scalar rxBytes
static const int VirtualMask
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void devIntrPost(uint32_t interrupts)
Interrupt management.
Tick write(PacketPtr pkt) override
IPR read of device register.
fifo_list::iterator iterator
const std::string & name()
#define SERIALIZE_SCALAR(scalar)
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
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...
void devIntrChangeMask(uint32_t newmask)
virtual void drainResume()
Resume execution after a successful drain.
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
uint64_t & regData64(Addr daddr)
Ports are used to interface objects to each other.
int countPacketsBefore(const_iterator i) const
Tick read(PacketPtr pkt) override
Memory Interface.
static const int VirtualShift
statistics::Scalar rxPackets
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
int ContextID
Globally unique thread context ID.
statistics::Scalar txBytes
void prepareRead(ContextID cpu, int index)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
PacketFifo::iterator rxFifoPtr
statistics::Scalar rxTcpChecksums
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void prepareWrite(ContextID cpu, int index)
std::ostream CheckpointOut
void serialize(CheckpointOut &cp) const override
Serialization stuff.
EventFunctionWrapper * intrEvent
void squash()
Squash the current event.
int countPacketsAfter(const_iterator i) const
void setLE(T v)
Set the value in the data pointer to v as little endian.
const registers::Info & regInfo(Addr daddr)
@ Running
Running normally.
Addr pciToDma(Addr pci_addr) const
statistics::Scalar totalVnicDistance
void transmit()
Retransmit event.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
void command(uint32_t command)
EventFunctionWrapper rxDmaEvent
statistics::Scalar txIpChecksums
bool scheduled() const
Determine if the current event is scheduled.
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Sun Jul 30 2023 01:56:56 for gem5 by doxygen 1.8.17