Go to the documentation of this file.
39 #include "debug/EthernetAll.hh"
49 using namespace networking;
80 intrDelay(
p.intr_delay), intrTick(0), cpuIntrEnable(false),
81 cpuPendingIntr(false), intrEvent(0), interface(NULL)
86 :
Base(
p), rxUnique(0), txUnique(0),
87 virtualRegs(
p.virtual_count < 1 ? 1 :
p.virtual_count),
88 rxFifo(
p.rx_fifo_size), txFifo(
p.tx_fifo_size),
89 rxKickTick(0), txKickTick(0),
91 rxDmaEvent([
this]{ rxDmaDone(); },
name()),
92 txDmaEvent([
this]{ txDmaDone(); },
name()),
93 dmaReadDelay(
p.dma_read_delay), dmaReadFactor(
p.dma_read_factor),
94 dmaWriteDelay(
p.dma_write_delay), dmaWriteFactor(
p.dma_write_factor),
95 sinicDeviceStats(
this)
97 interface = new Interface(
name() + ".int0", this);
105 : statistics::
Group(parent,
"SinicDevice"),
106 ADD_STAT(totalVnicDistance, statistics::units::Count::get(),
107 "Total vnic distance"),
108 ADD_STAT(numVnicDistance, statistics::units::Count::get(),
109 "Number of vnic distance measurements"),
110 ADD_STAT(maxVnicDistance, statistics::units::Count::get(),
111 "Maximum vnic distance"),
112 ADD_STAT(avgVnicDistance, statistics::units::Rate<
113 statistics::units::Count, statistics::units::Count>::get(),
114 "Average vnic distance", totalVnicDistance / numVnicDistance),
130 if (if_name ==
"interface")
141 panic(
"Trying to access a vnic that doesn't exist %d > %d\n",
152 using namespace registers;
158 uint64_t rxdone = vnic.
RxDone;
161 rxdone = set_RxDone_High(rxdone,
rxFifo.
size() >
regs.RxFifoHigh);
162 rxdone = set_RxDone_NotHigh(rxdone,
rxLow);
164 regs.RxDone = rxdone;
165 regs.RxWait = rxdone;
168 uint64_t txdone = vnic.
TxDone;
173 regs.TxDone = txdone;
174 regs.TxWait = txdone;
180 if (vnic != -1 &&
virtualRegs[vnic].rxPacketOffset > 0)
184 regs.RxStatus = set_RxStatus_Head(
regs.RxStatus, head);
205 assert(
BARs[0]->range().contains(daddr));
206 daddr -=
BARs[0]->addr();
213 panic(
"invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
219 panic(
"read %s (write only): "
220 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
225 panic(
"read %s (invalid size): "
226 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
232 [[maybe_unused]] uint64_t value = 0;
246 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
251 if (raddr == registers::IntrStatus)
296 assert(
BARs[0]->range().contains(daddr));
297 daddr -=
BARs[0]->addr();
304 panic(
"invalid register: cpu=%d, da=%#x pa=%#x size=%d",
309 panic(
"write %s (read only): "
310 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
314 panic(
"write %s (invalid size): "
315 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
321 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
323 pkt->
getLE<uint32_t>() : pkt->
getLE<uint64_t>(),
329 case registers::Config:
333 case registers::Command:
337 case registers::IntrStatus:
339 pkt->
getLE<uint32_t>());
342 case registers::IntrMask:
346 case registers::RxData:
347 if (registers::get_RxDone_Busy(vnic.
RxDone))
348 panic(
"receive machine busy with another request! rxState=%s",
352 vnic.
RxDone = registers::RxDone_Busy;
356 if (registers::get_RxData_Vaddr(pkt->
getLE<uint64_t>())) {
357 panic(
"vtophys not implemented in newmem");
359 DPRINTF(EthernetPIO,
"write RxData vnic %d (rxunique %d)\n",
364 DPRINTF(EthernetPIO,
"request new packet...appending to rxList\n");
367 DPRINTF(EthernetPIO,
"packet exists...appending to rxBusy\n");
377 case registers::TxData:
378 if (registers::get_TxDone_Busy(vnic.
TxDone))
379 panic(
"transmit machine busy with another request! txState=%s",
383 vnic.
TxDone = registers::TxDone_Busy;
385 if (registers::get_TxData_Vaddr(pkt->
getLE<uint64_t>())) {
386 panic(
"vtophys won't work here in newmem.\n");
388 DPRINTF(EthernetPIO,
"write TxData vnic %d (txunique %d)\n",
407 if ((interrupts & registers::Intr_Res))
408 panic(
"Cannot set a reserved interrupt");
410 regs.IntrStatus |= interrupts;
413 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
414 interrupts,
regs.IntrStatus,
regs.IntrMask);
416 interrupts =
regs.IntrStatus &
regs.IntrMask;
423 interrupts &= ~registers::Intr_RxHigh;
430 interrupts &= ~registers::Intr_TxLow;
434 if ((interrupts & registers::Intr_NoDelay) == 0)
443 if ((interrupts & registers::Intr_Res))
444 panic(
"Cannot clear a reserved interrupt");
446 regs.IntrStatus &= ~interrupts;
449 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
450 interrupts,
regs.IntrStatus,
regs.IntrMask);
452 if (!(
regs.IntrStatus &
regs.IntrMask))
459 if (
regs.IntrMask == newmask)
462 regs.IntrMask = newmask;
465 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
468 if (
regs.IntrStatus &
regs.IntrMask)
489 DPRINTF(EthernetIntr,
"interrupts not enabled.\n",
495 DPRINTF(EthernetIntr,
"don't need to schedule event...intrTick=%d\n",
505 DPRINTF(EthernetIntr,
"going to schedule an interrupt for intrTick=%d\n",
529 "would send an interrupt now, but there's already pending\n");
534 DPRINTF(EthernetIntr,
"posting interrupt\n");
554 DPRINTF(EthernetIntr,
"clearing cchip interrupt\n");
565 uint32_t changed =
regs.Config ^ newconf;
569 regs.Config = newconf;
571 if ((changed & registers::Config_IntEn)) {
574 if (
regs.IntrStatus &
regs.IntrMask)
581 if ((changed & registers::Config_TxEn)) {
587 if ((changed & registers::Config_RxEn)) {
597 if (
command & registers::Command_Intr)
600 if (
command & registers::Command_Reset)
607 using namespace registers;
613 regs.Config |= Config_RxThread;
615 regs.Config |= Config_TxThread;
617 regs.Config |= Config_RSS;
619 regs.Config |= Config_ZeroCopy;
621 regs.Config |= Config_DelayCopy;
622 if (
params().virtual_addr)
623 regs.Config |= Config_Vaddr;
626 panic(
"Can't delay copy and zero copy");
628 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
632 regs.ZeroCopyMark =
params().zero_copy_threshold;
643 if (
regs.RxMaxCopy <
regs.ZeroCopyMark)
644 panic(
"Must be able to copy at least as many bytes as the threshold");
646 if (
regs.ZeroCopySize >=
regs.ZeroCopyMark)
647 panic(
"The number of bytes to copy must be less than the threshold");
670 for (
int i = 0;
i < size; ++
i)
679 DPRINTF(EthernetDMA,
"end rx dma write paddr=%#x len=%d\n",
695 DPRINTF(EthernetSM,
"rxKick: rxState=%s (rxFifo.size=%d)\n",
699 DPRINTF(EthernetSM,
"rxKick: exiting, can't run till %d\n",
713 DPRINTF(EthernetSM,
"processing rxState=%s\n",
718 "processing rxState=%s for vnic %d (rxunique %d)\n",
724 if (debug::EthernetSM) {
727 for (
int i = 0;
i < size; ++
i) {
729 bool busy = registers::get_RxDone_Busy(vn->
RxDone);
745 "vnic %d %s (rxunique %d), packet %d, slack %d\n",
751 DPRINTF(EthernetSM,
"vnic %d unmapped (rxunique %d)\n",
763 panic(
"continuing vnic without packet\n");
766 "continue processing for vnic %d (rxunique %d)\n",
783 DPRINTF(EthernetSM,
"receive waiting for data. Nothing to do.\n");
788 panic(
"Not idle, but nothing to do!");
797 "processing new packet for vnic %d (rxunique %d)\n",
812 DPRINTF(Ethernet,
"ID is %d\n",
ip->id());
813 vnic->
rxDoneData |= registers::RxDone_IpPacket;
816 DPRINTF(EthernetCksum,
"Rx IP Checksum Error\n");
817 vnic->
rxDoneData |= registers::RxDone_IpError;
823 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
826 vnic->
rxDoneData |= registers::RxDone_TcpPacket;
829 DPRINTF(EthernetCksum,
"Rx TCP Checksum Error\n");
830 vnic->
rxDoneData |= registers::RxDone_TcpError;
833 vnic->
rxDoneData |= registers::RxDone_UdpPacket;
835 if (
cksum(udp) != 0) {
836 DPRINTF(EthernetCksum,
"Rx UDP Checksum Error\n");
837 vnic->
rxDoneData |= registers::RxDone_UdpError;
850 rxDmaLen = std::min<unsigned>(registers::get_RxData_Len(vnic->
RxData),
857 if ((registers::get_Config_ZeroCopy(
regs.Config) ||
858 registers::get_Config_DelayCopy(
regs.Config)) &&
859 !registers::get_RxData_NoDelay(vnic->
RxData) &&
rxLow) {
874 DPRINTF(EthernetSM,
"receive machine still copying\n");
879 vnic->
RxDone |= registers::RxDone_Complete;
891 "rxKick: packet complete on vnic %d (rxunique %d)\n",
902 vnic->
RxDone |= registers::RxDone_More;
903 vnic->
RxDone = registers::set_RxDone_CopyLen(vnic->
RxDone,
906 "rxKick: packet not complete on vnic %d (rxunique %d): "
929 panic(
"Invalid rxState!");
932 DPRINTF(EthernetSM,
"entering next rxState=%s\n",
941 DPRINTF(EthernetSM,
"rx state machine exited rxState=%s\n",
950 DPRINTF(EthernetDMA,
"tx dma read paddr=%#x len=%d\n",
965 DPRINTF(Ethernet,
"nothing to transmit\n");
972 DPRINTF(Ethernet,
"Packet Transmit: failed txFifo available %d\n",
979 if (debug::Ethernet) {
982 DPRINTF(Ethernet,
"ID is %d\n",
ip->id());
986 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
994 DDUMP(EthernetData, packet->data, packet->length);
998 DPRINTF(Ethernet,
"Packet Transmit: successful txFifo Available %d\n",
1001 interrupts = registers::Intr_TxPacket;
1003 interrupts |= registers::Intr_TxLow;
1011 DPRINTF(EthernetSM,
"txKick: txState=%s (txFifo.size=%d)\n",
1015 DPRINTF(EthernetSM,
"txKick: exiting, can't run till %d\n",
1029 assert(registers::get_TxDone_Busy(vnic->
TxDone));
1032 txPacket = std::make_shared<EthPacketData>(16384);
1037 registers::get_TxData_Len(vnic->
TxData)) {
1038 DPRINTF(EthernetSM,
"transmit fifo full. Nothing to do.\n");
1058 DPRINTF(EthernetSM,
"transmit machine still copying\n");
1065 if ((vnic->
TxData & registers::TxData_More)) {
1073 if ((vnic->
TxData & registers::TxData_Checksum)) {
1109 panic(
"Invalid txState!");
1112 DPRINTF(EthernetSM,
"entering next txState=%s\n",
1121 DPRINTF(EthernetSM,
"tx state machine exited txState=%s\n",
1129 DPRINTF(Ethernet,
"transfer complete: txFifo empty...nothing to do\n");
1133 DPRINTF(Ethernet,
"transfer complete: data in txFifo...schedule xmit\n");
1141 if (!registers::get_Config_Filter(
regs.Config))
1144 panic(
"receive filter not implemented\n");
1155 DPRINTF(Ethernet,
"Receiving packet from wire, rxFifo Available is %d\n",
1159 DPRINTF(Ethernet,
"receive disabled...packet dropped\n");
1164 DPRINTF(Ethernet,
"packet filtered...dropped\n");
1173 "packet will not fit in receive buffer...packet dropped\n");
1217 Tick intrEventTick = 0;
1240 if (intrEventTick) {
1256 panic(
"can't serialize with an in flight dma request rxState=%s",
1260 panic(
"can't serialize with an in flight dma request txState=%s",
1277 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1287 paramOut(cp,
reg +
".rxPacketExists", rxPacketExists);
1288 if (rxPacketExists) {
1314 VirtualList::const_iterator
i, end;
1317 int rxListSize =
count;
1322 int rxBusySize =
count;
1327 int txListSize =
count;
1346 bool txPacketExists =
txPacket !=
nullptr;
1348 if (txPacketExists) {
1349 txPacket->serialize(
"txPacket", cp);
1385 for (
int i = 0;
i < rxListSize; ++
i) {
1394 for (
int i = 0;
i < rxBusySize; ++
i) {
1403 for (
int i = 0;
i < txListSize; ++
i) {
1437 bool txPacketExists;
1440 if (txPacketExists) {
1441 txPacket = std::make_shared<EthPacketData>(16384);
1442 txPacket->unserialize(
"txPacket", cp);
1453 int virtualRegsSize;
1457 for (
int i = 0;
i < virtualRegsSize; ++
i) {
1469 bool rxPacketExists;
1470 paramIn(cp,
reg +
".rxPacketExists", rxPacketExists);
1471 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)
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.
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
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)
struct gem5::sinic::Device::@96 regs
device register file
@ 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 Wed May 4 2022 12:13:57 for gem5 by doxygen 1.8.17