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"),
107 "Total vnic distance"),
109 "Number of vnic distance measurements"),
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>(),
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) {
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
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...
Cycles is a wrapper class for representing cycle counts, i.e.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
Dummy class to keep the Python class hierarchy in sync with the C++ object hierarchy.
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
bool sendPacket(EthPacketPtr packet)
virtual std::string name() const
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
void unserialize(const std::string &base, CheckpointIn &cp)
bool push(EthPacketPtr ptr)
int countPacketsBefore(const_iterator i) const
int countPacketsAfter(const_iterator i) const
fifo_list::iterator iterator
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
PCIConfig config
The current config space.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Addr pciToDma(Addr pci_addr) const
std::array< PciBar *, 6 > BARs
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
Ports are used to interface objects to each other.
void cpuIntrPost(Tick when)
EventFunctionWrapper * intrEvent
void serialize(CheckpointOut &cp) const override
Serialization stuff.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool cpuIntrPending() const
EventFunctionWrapper txEvent
void transmit()
Retransmit event.
bool rxFilter(const EthPacketPtr &packet)
receive address filter
void prepareRead(ContextID cpu, int index)
Tick write(PacketPtr pkt) override
IPR read of device register.
PacketFifo::iterator rxFifoPtr
uint32_t & regData32(Addr daddr)
struct gem5::sinic::Device::@314 regs
device register file
void changeConfig(uint32_t newconfig)
device configuration
bool recvPacket(EthPacketPtr packet)
device ethernet interface
void devIntrPost(uint32_t interrupts)
Interrupt management.
EventFunctionWrapper txDmaEvent
void devIntrChangeMask(uint32_t newmask)
void prepareWrite(ContextID cpu, int index)
void rxDmaDone()
DMA parameters.
RxState
Receive State Machine States.
Tick read(PacketPtr pkt) override
Memory Interface.
TxState
Transmit State Machine states.
EventFunctionWrapper rxDmaEvent
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void serialize(CheckpointOut &cp) const override
Serialization stuff.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void command(uint32_t command)
void resetStats() override
Callback to reset stats.
uint64_t & regData64(Addr daddr)
virtual void drainResume() override
Resume execution after a successful drain.
gem5::sinic::Device::DeviceStats sinicDeviceStats
void prepareIO(ContextID cpu, int index)
void devIntrClear(uint32_t interrupts=registers::Intr_All)
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
virtual void drainResume()
Resume execution after a successful drain.
DrainState drainState() const
Return the current drain state of an object.
@ Running
Running normally.
bool scheduled() const
Determine if the current event is scheduled.
void squash()
Squash the current event.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
Tick when() const
Get the time that the event is scheduled.
uint16_t cksum(const IpPtr &ptr)
#define panic(...)
This implements a cprintf based panic() function.
const Params & params() const
virtual void resetStats()
Callback to reset stats.
static const int VirtualMask
static const int VirtualShift
const registers::Info & regInfo(Addr daddr)
const char * TxStateStrings[]
const char * RxStateStrings[]
bool regValid(Addr daddr)
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
uint64_t Tick
Tick count type.
int ContextID
Globally unique thread context ID.
std::string csprintf(const char *format, const Args &...args)
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
std::shared_ptr< EthPacketData > EthPacketPtr
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
statistics::Scalar txPackets
statistics::Scalar txIpChecksums
statistics::Scalar txBytes
statistics::Scalar rxTcpChecksums
statistics::Scalar rxPackets
statistics::Scalar txUdpChecksums
statistics::Scalar rxUdpChecksums
statistics::Scalar rxIpChecksums
statistics::Scalar txTcpChecksums
statistics::Scalar rxBytes
statistics::Scalar totalVnicDistance
statistics::Scalar maxVnicDistance
statistics::Scalar numVnicDistance
DeviceStats(statistics::Group *parent)
PacketFifo::iterator rxIndex
const std::string & name()