gem5 v24.0.0.0
Loading...
Searching...
No Matches
sinic.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "dev/net/sinic.hh"
30
31#include <deque>
32#include <limits>
33#include <string>
34
35#include "base/compiler.hh"
36#include "base/debug.hh"
37#include "base/inet.hh"
38#include "base/types.hh"
39#include "debug/EthernetAll.hh"
40#include "dev/net/etherlink.hh"
41#include "mem/packet.hh"
42#include "mem/packet_access.hh"
43#include "sim/eventq.hh"
44#include "sim/stats.hh"
45
46namespace gem5
47{
48
49using namespace networking;
50
51namespace sinic
52{
53
54const char *RxStateStrings[] =
55{
56 "rxIdle",
57 "rxFifoBlock",
58 "rxBeginCopy",
59 "rxCopy",
60 "rxCopyDone"
61};
62
63const char *TxStateStrings[] =
64{
65 "txIdle",
66 "txFifoBlock",
67 "txBeginCopy",
68 "txCopy",
69 "txCopyDone"
70};
71
72
74//
75// Sinic PCI Device
76//
78 : EtherDevBase(p), rxEnable(false), txEnable(false),
79 intrDelay(p.intr_delay), intrTick(0), cpuIntrEnable(false),
80 cpuPendingIntr(false), intrEvent(0), interface(NULL)
81{
82}
83
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),
89 txEvent([this]{ txEventTransmit(); }, name()),
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)
95{
96 interface = new Interface(name() + ".int0", this);
97 reset();
98}
99
102
104 : statistics::Group(parent, "SinicDevice"),
105 ADD_STAT(totalVnicDistance, statistics::units::Count::get(),
106 "Total vnic distance"),
107 ADD_STAT(numVnicDistance, statistics::units::Count::get(),
108 "Number of vnic distance measurements"),
109 ADD_STAT(maxVnicDistance, statistics::units::Count::get(),
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),
114 _maxVnicDistance(0)
115{
116}
117
118void
125
126Port &
127Device::getPort(const std::string &if_name, PortID idx)
128{
129 if (if_name == "interface")
130 return *interface;
131 return EtherDevBase::getPort(if_name, idx);
132}
133
134
135void
137{
138 int size = virtualRegs.size();
139 if (index > size)
140 panic("Trying to access a vnic that doesn't exist %d > %d\n",
141 index, size);
142}
143
144//add stats for head of line blocking
145//add stats for average fifo length
146//add stats for average number of vnics busy
147
148void
150{
151 using namespace registers;
152 prepareIO(cpu, index);
153
155
156 // update rx registers
157 uint64_t rxdone = vnic.RxDone;
158 rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));
159 rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());
160 rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoHigh);
161 rxdone = set_RxDone_NotHigh(rxdone, rxLow);
162 regs.RxData = vnic.RxData;
163 regs.RxDone = rxdone;
164 regs.RxWait = rxdone;
165
166 // update tx regsiters
167 uint64_t txdone = vnic.TxDone;
168 txdone = set_TxDone_Packets(txdone, txFifo.packets());
169 txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
170 txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoLow);
171 regs.TxData = vnic.TxData;
172 regs.TxDone = txdone;
173 regs.TxWait = txdone;
174
175 int head = 0xffff;
176
177 if (!rxFifo.empty()) {
178 int vnic = rxFifo.begin()->priv;
179 if (vnic != -1 && virtualRegs[vnic].rxPacketOffset > 0)
180 head = vnic;
181 }
182
183 regs.RxStatus = set_RxStatus_Head(regs.RxStatus, head);
184 regs.RxStatus = set_RxStatus_Busy(regs.RxStatus, rxBusyCount);
185 regs.RxStatus = set_RxStatus_Mapped(regs.RxStatus, rxMappedCount);
186 regs.RxStatus = set_RxStatus_Dirty(regs.RxStatus, rxDirtyCount);
187}
188
189void
191{
192 prepareIO(cpu, index);
193}
194
198Tick
200{
201 assert(config.command & PCI_CMD_MSE);
202
203 Addr daddr = pkt->getAddr();
204 assert(BARs[0]->range().contains(daddr));
205 daddr -= BARs[0]->addr();
206
207 ContextID cpu = pkt->req->contextId();
209 Addr raddr = daddr & registers::VirtualMask;
210
211 if (!regValid(raddr)) {
212 panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
213 cpu, index, daddr, pkt->getAddr(), pkt->getSize());
214 }
215
216 const registers::Info &info = regInfo(raddr);
217 if (!info.read) {
218 panic("read %s (write only): "
219 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
220 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
221 }
222
223 if (info.size != pkt->getSize()) {
224 panic("read %s (invalid size): "
225 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
226 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
227 }
228
229 prepareRead(cpu, index);
230
231 [[maybe_unused]] uint64_t value = 0;
232 if (pkt->getSize() == 4) {
233 uint32_t reg = regData32(raddr);
234 pkt->setLE(reg);
235 value = reg;
236 }
237
238 if (pkt->getSize() == 8) {
239 uint64_t reg = regData64(raddr);
240 pkt->setLE(reg);
241 value = reg;
242 }
243
244 DPRINTF(EthernetPIO,
245 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
246 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);
247
248 // reading the interrupt status register has the side effect of
249 // clearing it
250 if (raddr == registers::IntrStatus)
251 devIntrClear();
252
253 return pioDelay;
254}
255
289Tick
291{
292 assert(config.command & PCI_CMD_MSE);
293
294 Addr daddr = pkt->getAddr();
295 assert(BARs[0]->range().contains(daddr));
296 daddr -= BARs[0]->addr();
297
298 ContextID cpu = pkt->req->contextId();
300 Addr raddr = daddr & registers::VirtualMask;
301
302 if (!regValid(raddr))
303 panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
304 cpu, daddr, pkt->getAddr(), pkt->getSize());
305
306 const registers::Info &info = regInfo(raddr);
307 if (!info.write)
308 panic("write %s (read only): "
309 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
310 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
311
312 if (pkt->getSize() != info.size)
313 panic("write %s (invalid size): "
314 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
315 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
316
318
319 DPRINTF(EthernetPIO,
320 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
321 info.name, index, cpu, info.size == 4 ?
322 pkt->getLE<uint32_t>() : pkt->getLE<uint64_t>(),
323 daddr, pkt->getAddr(), pkt->getSize());
324
325 prepareWrite(cpu, index);
326
327 switch (raddr) {
328 case registers::Config:
329 changeConfig(pkt->getLE<uint32_t>());
330 break;
331
332 case registers::Command:
333 command(pkt->getLE<uint32_t>());
334 break;
335
336 case registers::IntrStatus:
337 devIntrClear(regs.IntrStatus &
338 pkt->getLE<uint32_t>());
339 break;
340
341 case registers::IntrMask:
342 devIntrChangeMask(pkt->getLE<uint32_t>());
343 break;
344
345 case registers::RxData:
346 if (registers::get_RxDone_Busy(vnic.RxDone))
347 panic("receive machine busy with another request! rxState=%s",
349
350 vnic.rxUnique = rxUnique++;
351 vnic.RxDone = registers::RxDone_Busy;
352 vnic.RxData = pkt->getLE<uint64_t>();
353 rxBusyCount++;
354
355 if (registers::get_RxData_Vaddr(pkt->getLE<uint64_t>())) {
356 panic("vtophys not implemented in newmem");
357 } else {
358 DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
359 index, vnic.rxUnique);
360 }
361
362 if (vnic.rxIndex == rxFifo.end()) {
363 DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
364 rxList.push_back(index);
365 } else {
366 DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");
367 rxBusy.push_back(index);
368 }
369
370 if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {
372 rxKick();
373 }
374 break;
375
376 case registers::TxData:
377 if (registers::get_TxDone_Busy(vnic.TxDone))
378 panic("transmit machine busy with another request! txState=%s",
380
381 vnic.txUnique = txUnique++;
382 vnic.TxDone = registers::TxDone_Busy;
383
384 if (registers::get_TxData_Vaddr(pkt->getLE<uint64_t>())) {
385 panic("vtophys won't work here in newmem.\n");
386 } else {
387 DPRINTF(EthernetPIO, "write TxData vnic %d (txunique %d)\n",
388 index, vnic.txUnique);
389 }
390
391 if (txList.empty() || txList.front() != index)
392 txList.push_back(index);
393 if (txEnable && txState == txIdle && txList.front() == index) {
395 txKick();
396 }
397 break;
398 }
399
400 return pioDelay;
401}
402
403void
404Device::devIntrPost(uint32_t interrupts)
405{
406 if ((interrupts & registers::Intr_Res))
407 panic("Cannot set a reserved interrupt");
408
409 regs.IntrStatus |= interrupts;
410
411 DPRINTF(EthernetIntr,
412 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
413 interrupts, regs.IntrStatus, regs.IntrMask);
414
415 interrupts = regs.IntrStatus & regs.IntrMask;
416
417 // Intr_RxHigh is special, we only signal it if we've emptied the fifo
418 // and then filled it above the high watermark
419 if (rxEmpty)
420 rxEmpty = false;
421 else
422 interrupts &= ~registers::Intr_RxHigh;
423
424 // Intr_TxLow is special, we only signal it if we've filled up the fifo
425 // and then dropped below the low watermark
426 if (txFull)
427 txFull = false;
428 else
429 interrupts &= ~registers::Intr_TxLow;
430
431 if (interrupts) {
432 Tick when = curTick();
433 if ((interrupts & registers::Intr_NoDelay) == 0)
434 when += intrDelay;
435 cpuIntrPost(when);
436 }
437}
438
439void
440Device::devIntrClear(uint32_t interrupts)
441{
442 if ((interrupts & registers::Intr_Res))
443 panic("Cannot clear a reserved interrupt");
444
445 regs.IntrStatus &= ~interrupts;
446
447 DPRINTF(EthernetIntr,
448 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
449 interrupts, regs.IntrStatus, regs.IntrMask);
450
451 if (!(regs.IntrStatus & regs.IntrMask))
452 cpuIntrClear();
453}
454
455void
457{
458 if (regs.IntrMask == newmask)
459 return;
460
461 regs.IntrMask = newmask;
462
463 DPRINTF(EthernetIntr,
464 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
465 regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
466
467 if (regs.IntrStatus & regs.IntrMask)
469 else
470 cpuIntrClear();
471}
472
473void
475{
476 // If the interrupt you want to post is later than an interrupt
477 // already scheduled, just let it post in the coming one and don't
478 // schedule another.
479 // HOWEVER, must be sure that the scheduled intrTick is in the
480 // future (this was formerly the source of a bug)
485 assert(when >= curTick());
486 assert(intrTick >= curTick() || intrTick == 0);
487 if (!cpuIntrEnable) {
488 DPRINTF(EthernetIntr, "interrupts not enabled.\n",
489 intrTick);
490 return;
491 }
492
493 if (when > intrTick && intrTick != 0) {
494 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
495 intrTick);
496 return;
497 }
498
499 intrTick = when;
500 if (intrTick < curTick()) {
501 intrTick = curTick();
502 }
503
504 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
505 intrTick);
506
507 if (intrEvent)
508 intrEvent->squash();
509
511 name(), true);
513}
514
515void
517{
518 assert(intrTick == curTick());
519
520 // Whether or not there's a pending interrupt, we don't care about
521 // it anymore
522 intrEvent = 0;
523 intrTick = 0;
524
525 // Don't send an interrupt if there's already one
526 if (cpuPendingIntr) {
527 DPRINTF(EthernetIntr,
528 "would send an interrupt now, but there's already pending\n");
529 } else {
530 // Send interrupt
531 cpuPendingIntr = true;
532
533 DPRINTF(EthernetIntr, "posting interrupt\n");
534 intrPost();
535 }
536}
537
538void
540{
541 if (!cpuPendingIntr)
542 return;
543
544 if (intrEvent) {
545 intrEvent->squash();
546 intrEvent = 0;
547 }
548
549 intrTick = 0;
550
551 cpuPendingIntr = false;
552
553 DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
554 intrClear();
555}
556
557bool
560
561void
562Device::changeConfig(uint32_t newconf)
563{
564 uint32_t changed = regs.Config ^ newconf;
565 if (!changed)
566 return;
567
568 regs.Config = newconf;
569
570 if ((changed & registers::Config_IntEn)) {
571 cpuIntrEnable = regs.Config & registers::Config_IntEn;
572 if (cpuIntrEnable) {
573 if (regs.IntrStatus & regs.IntrMask)
575 } else {
576 cpuIntrClear();
577 }
578 }
579
580 if ((changed & registers::Config_TxEn)) {
581 txEnable = regs.Config & registers::Config_TxEn;
582 if (txEnable)
583 txKick();
584 }
585
586 if ((changed & registers::Config_RxEn)) {
587 rxEnable = regs.Config & registers::Config_RxEn;
588 if (rxEnable)
589 rxKick();
590 }
591}
592
593void
595{
596 if (command & registers::Command_Intr)
597 devIntrPost(registers::Intr_Soft);
598
599 if (command & registers::Command_Reset)
600 reset();
601}
602
603void
605{
606 using namespace registers;
607
608 memset(&regs, 0, sizeof(regs));
609
610 regs.Config = 0;
611 if (params().rx_thread)
612 regs.Config |= Config_RxThread;
613 if (params().tx_thread)
614 regs.Config |= Config_TxThread;
615 if (params().rss)
616 regs.Config |= Config_RSS;
617 if (params().zero_copy)
618 regs.Config |= Config_ZeroCopy;
619 if (params().delay_copy)
620 regs.Config |= Config_DelayCopy;
621 if (params().virtual_addr)
622 regs.Config |= Config_Vaddr;
623
624 if (params().delay_copy && params().zero_copy)
625 panic("Can't delay copy and zero copy");
626
627 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
628 regs.RxMaxCopy = params().rx_max_copy;
629 regs.TxMaxCopy = params().tx_max_copy;
630 regs.ZeroCopySize = params().zero_copy_size;
631 regs.ZeroCopyMark = params().zero_copy_threshold;
632 regs.VirtualCount = params().virtual_count;
633 regs.RxMaxIntr = params().rx_max_intr;
634 regs.RxFifoSize = params().rx_fifo_size;
635 regs.TxFifoSize = params().tx_fifo_size;
636 regs.RxFifoLow = params().rx_fifo_low_mark;
637 regs.TxFifoLow = params().tx_fifo_threshold;
638 regs.RxFifoHigh = params().rx_fifo_threshold;
639 regs.TxFifoHigh = params().tx_fifo_high_mark;
640 regs.HwAddr = params().hardware_address;
641
642 if (regs.RxMaxCopy < regs.ZeroCopyMark)
643 panic("Must be able to copy at least as many bytes as the threshold");
644
645 if (regs.ZeroCopySize >= regs.ZeroCopyMark)
646 panic("The number of bytes to copy must be less than the threshold");
647
648 rxList.clear();
649 rxBusy.clear();
650 rxActive = -1;
651 txList.clear();
652 rxBusyCount = 0;
653 rxDirtyCount = 0;
654 rxMappedCount = 0;
655
656 rxState = rxIdle;
657 txState = txIdle;
658
659 rxFifo.clear();
660 rxFifoPtr = rxFifo.end();
661 txFifo.clear();
662 rxEmpty = false;
663 rxLow = true;
664 txFull = false;
665
666 int size = virtualRegs.size();
667 virtualRegs.clear();
668 virtualRegs.resize(size);
669 for (int i = 0; i < size; ++i)
670 virtualRegs[i].rxIndex = rxFifo.end();
671}
672
673void
675{
676 assert(rxState == rxCopy);
678 DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n",
680 DDUMP(EthernetData, rxDmaData, rxDmaLen);
681
682 // If the transmit state machine has a pending DMA, let it go first
683 if (txState == txBeginCopy)
684 txKick();
685
686 rxKick();
687}
688
689void
691{
692 VirtualReg *vnic = NULL;
693
694 DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n",
696
697 if (rxKickTick > curTick()) {
698 DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n",
699 rxKickTick);
700 return;
701 }
702
703 next:
704 rxFifo.check();
705 if (rxState == rxIdle)
706 goto exit;
707
708 if (rxActive == -1) {
709 if (rxState != rxFifoBlock)
710 panic("no active vnic while in state %s", RxStateStrings[rxState]);
711
712 DPRINTF(EthernetSM, "processing rxState=%s\n",
714 } else {
715 vnic = &virtualRegs[rxActive];
716 DPRINTF(EthernetSM,
717 "processing rxState=%s for vnic %d (rxunique %d)\n",
719 }
720
721 switch (rxState) {
722 case rxFifoBlock:
723 if (debug::EthernetSM) {
725 int size = virtualRegs.size();
726 for (int i = 0; i < size; ++i) {
727 VirtualReg *vn = &virtualRegs[i];
728 bool busy = registers::get_RxDone_Busy(vn->RxDone);
729 if (vn->rxIndex != end) {
730#ifndef NDEBUG
731 bool dirty = vn->rxPacketOffset > 0;
732 const char *status;
733
734 if (busy && dirty)
735 status = "busy,dirty";
736 else if (busy)
737 status = "busy";
738 else if (dirty)
739 status = "dirty";
740 else
741 status = "mapped";
742
743 DPRINTF(EthernetSM,
744 "vnic %d %s (rxunique %d), packet %d, slack %d\n",
745 i, status, vn->rxUnique,
747 vn->rxIndex->slack);
748#endif
749 } else if (busy) {
750 DPRINTF(EthernetSM, "vnic %d unmapped (rxunique %d)\n",
751 i, vn->rxUnique);
752 }
753 }
754 }
755
756 if (!rxBusy.empty()) {
757 rxActive = rxBusy.front();
758 rxBusy.pop_front();
759 vnic = &virtualRegs[rxActive];
760
761 if (vnic->rxIndex == rxFifo.end())
762 panic("continuing vnic without packet\n");
763
764 DPRINTF(EthernetSM,
765 "continue processing for vnic %d (rxunique %d)\n",
766 rxActive, vnic->rxUnique);
767
769
770 int vnic_distance = rxFifo.countPacketsBefore(vnic->rxIndex);
771 sinicDeviceStats.totalVnicDistance += vnic_distance;
773 if (vnic_distance > sinicDeviceStats._maxVnicDistance) {
774 sinicDeviceStats.maxVnicDistance = vnic_distance;
775 sinicDeviceStats._maxVnicDistance = vnic_distance;
776 }
777
778 break;
779 }
780
781 if (rxFifoPtr == rxFifo.end()) {
782 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
783 goto exit;
784 }
785
786 if (rxList.empty())
787 panic("Not idle, but nothing to do!");
788
789 assert(!rxFifo.empty());
790
791 rxActive = rxList.front();
792 rxList.pop_front();
793 vnic = &virtualRegs[rxActive];
794
795 DPRINTF(EthernetSM,
796 "processing new packet for vnic %d (rxunique %d)\n",
797 rxActive, vnic->rxUnique);
798
799 // Grab a new packet from the fifo.
800 vnic->rxIndex = rxFifoPtr++;
801 vnic->rxIndex->priv = rxActive;
802 vnic->rxPacketOffset = 0;
803 vnic->rxPacketBytes = vnic->rxIndex->packet->length;
804 assert(vnic->rxPacketBytes);
806
807 vnic->rxDoneData = 0;
808 /* scope for variables */ {
809 IpPtr ip(vnic->rxIndex->packet);
810 if (ip) {
811 DPRINTF(Ethernet, "ID is %d\n", ip->id());
812 vnic->rxDoneData |= registers::RxDone_IpPacket;
814 if (cksum(ip) != 0) {
815 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
816 vnic->rxDoneData |= registers::RxDone_IpError;
817 }
818 TcpPtr tcp(ip);
819 UdpPtr udp(ip);
820 if (tcp) {
821 DPRINTF(Ethernet,
822 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
823 tcp->sport(), tcp->dport(), tcp->seq(),
824 tcp->ack());
825 vnic->rxDoneData |= registers::RxDone_TcpPacket;
827 if (cksum(tcp) != 0) {
828 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
829 vnic->rxDoneData |= registers::RxDone_TcpError;
830 }
831 } else if (udp) {
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;
837 }
838 }
839 }
840 }
842 break;
843
844 case rxBeginCopy:
846 goto exit;
847
848 rxDmaAddr = pciToDma(registers::get_RxData_Addr(vnic->RxData));
849 rxDmaLen = std::min<unsigned>(registers::get_RxData_Len(vnic->RxData),
850 vnic->rxPacketBytes);
851
852 /*
853 * if we're doing zero/delay copy and we're below the fifo
854 * threshold, see if we should try to do the zero/defer copy
855 */
856 if ((registers::get_Config_ZeroCopy(regs.Config) ||
857 registers::get_Config_DelayCopy(regs.Config)) &&
858 !registers::get_RxData_NoDelay(vnic->RxData) && rxLow) {
859 if (rxDmaLen > regs.ZeroCopyMark)
860 rxDmaLen = regs.ZeroCopySize;
861 }
862 rxDmaData = vnic->rxIndex->packet->data + vnic->rxPacketOffset;
863 rxState = rxCopy;
864 if (rxDmaAddr == 1LL) {
866 break;
867 }
868
870 break;
871
872 case rxCopy:
873 DPRINTF(EthernetSM, "receive machine still copying\n");
874 goto exit;
875
876 case rxCopyDone:
877 vnic->RxDone = vnic->rxDoneData;
878 vnic->RxDone |= registers::RxDone_Complete;
879 rxBusyCount--;
880
881 if (vnic->rxPacketBytes == rxDmaLen) {
882 if (vnic->rxPacketOffset)
883 rxDirtyCount--;
884
885 // Packet is complete. Indicate how many bytes were copied
886 vnic->RxDone =
887 registers::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen);
888
889 DPRINTF(EthernetSM,
890 "rxKick: packet complete on vnic %d (rxunique %d)\n",
891 rxActive, vnic->rxUnique);
892 rxFifo.remove(vnic->rxIndex);
893 vnic->rxIndex = rxFifo.end();
895 } else {
896 if (!vnic->rxPacketOffset)
897 rxDirtyCount++;
898
899 vnic->rxPacketBytes -= rxDmaLen;
900 vnic->rxPacketOffset += rxDmaLen;
901 vnic->RxDone |= registers::RxDone_More;
902 vnic->RxDone = registers::set_RxDone_CopyLen(vnic->RxDone,
903 vnic->rxPacketBytes);
904 DPRINTF(EthernetSM,
905 "rxKick: packet not complete on vnic %d (rxunique %d): "
906 "%d bytes left\n",
907 rxActive, vnic->rxUnique, vnic->rxPacketBytes);
908 }
909
910 rxActive = -1;
911 rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock;
912
913 if (rxFifo.empty()) {
914 devIntrPost(registers::Intr_RxEmpty);
915 rxEmpty = true;
916 }
917
918 if (rxFifo.size() < regs.RxFifoLow)
919 rxLow = true;
920
921 if (rxFifo.size() > regs.RxFifoHigh)
922 rxLow = false;
923
924 devIntrPost(registers::Intr_RxDMA);
925 break;
926
927 default:
928 panic("Invalid rxState!");
929 }
930
931 DPRINTF(EthernetSM, "entering next rxState=%s\n",
933
934 goto next;
935
936 exit:
940 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
942}
943
944void
946{
947 assert(txState == txCopy);
949 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
951 DDUMP(EthernetData, txDmaData, txDmaLen);
952
953 // If the receive state machine has a pending DMA, let it go first
954 if (rxState == rxBeginCopy)
955 rxKick();
956
957 txKick();
958}
959
960void
962{
963 if (txFifo.empty()) {
964 DPRINTF(Ethernet, "nothing to transmit\n");
965 return;
966 }
967
968 uint32_t interrupts;
969 EthPacketPtr packet = txFifo.front();
970 if (!interface->sendPacket(packet)) {
971 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
972 txFifo.avail());
973 return;
974 }
975
976 txFifo.pop();
977#if TRACING_ON
978 if (debug::Ethernet) {
979 IpPtr ip(packet);
980 if (ip) {
981 DPRINTF(Ethernet, "ID is %d\n", ip->id());
982 TcpPtr tcp(ip);
983 if (tcp) {
984 DPRINTF(Ethernet,
985 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
986 tcp->sport(), tcp->dport(), tcp->seq(),
987 tcp->ack());
988 }
989 }
990 }
991#endif
992
993 DDUMP(EthernetData, packet->data, packet->length);
994 etherDeviceStats.txBytes += packet->length;
996
997 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
998 txFifo.avail());
999
1000 interrupts = registers::Intr_TxPacket;
1001 if (txFifo.size() < regs.TxFifoLow)
1002 interrupts |= registers::Intr_TxLow;
1003 devIntrPost(interrupts);
1004}
1005
1006void
1008{
1009 VirtualReg *vnic;
1010 DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n",
1012
1013 if (txKickTick > curTick()) {
1014 DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n",
1015 txKickTick);
1016 return;
1017 }
1018
1019 next:
1020 if (txState == txIdle)
1021 goto exit;
1022
1023 assert(!txList.empty());
1024 vnic = &virtualRegs[txList.front()];
1025
1026 switch (txState) {
1027 case txFifoBlock:
1028 assert(registers::get_TxDone_Busy(vnic->TxDone));
1029 if (!txPacket) {
1030 // Grab a new packet from the fifo.
1031 txPacket = std::make_shared<EthPacketData>(16384);
1032 txPacketOffset = 0;
1033 }
1034
1035 if (txFifo.avail() - txPacket->length <
1036 registers::get_TxData_Len(vnic->TxData)) {
1037 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
1038 goto exit;
1039 }
1040
1042 break;
1043
1044 case txBeginCopy:
1046 goto exit;
1047
1048 txDmaAddr = pciToDma(registers::get_TxData_Addr(vnic->TxData));
1049 txDmaLen = registers::get_TxData_Len(vnic->TxData);
1051 txState = txCopy;
1052
1054 break;
1055
1056 case txCopy:
1057 DPRINTF(EthernetSM, "transmit machine still copying\n");
1058 goto exit;
1059
1060 case txCopyDone:
1061 vnic->TxDone = txDmaLen | registers::TxDone_Complete;
1062 txPacket->simLength += txDmaLen;
1063 txPacket->length += txDmaLen;
1064 if ((vnic->TxData & registers::TxData_More)) {
1066 txState = txIdle;
1067 devIntrPost(registers::Intr_TxDMA);
1068 break;
1069 }
1070
1071 assert(txPacket->length <= txFifo.avail());
1072 if ((vnic->TxData & registers::TxData_Checksum)) {
1073 IpPtr ip(txPacket);
1074 if (ip) {
1075 TcpPtr tcp(ip);
1076 if (tcp) {
1077 tcp->sum(0);
1078 tcp->sum(cksum(tcp));
1080 }
1081
1082 UdpPtr udp(ip);
1083 if (udp) {
1084 udp->sum(0);
1085 udp->sum(cksum(udp));
1087 }
1088
1089 ip->sum(0);
1090 ip->sum(cksum(ip));
1092 }
1093 }
1094
1096 if (txFifo.avail() < regs.TxMaxCopy) {
1097 devIntrPost(registers::Intr_TxFull);
1098 txFull = true;
1099 }
1100 txPacket = 0;
1101 transmit();
1102 txList.pop_front();
1103 txState = txList.empty() ? txIdle : txFifoBlock;
1104 devIntrPost(registers::Intr_TxDMA);
1105 break;
1106
1107 default:
1108 panic("Invalid txState!");
1109 }
1110
1111 DPRINTF(EthernetSM, "entering next txState=%s\n",
1113
1114 goto next;
1115
1116 exit:
1120 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1122}
1123
1124void
1126{
1127 if (txFifo.empty()) {
1128 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
1129 return;
1130 }
1131
1132 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
1133
1134 reschedule(txEvent, clockEdge(Cycles(1)), true);
1135}
1136
1137bool
1139{
1140 if (!registers::get_Config_Filter(regs.Config))
1141 return false;
1142
1143 panic("receive filter not implemented\n");
1144 bool drop = true;
1145 return drop;
1146}
1147
1148bool
1150{
1151 etherDeviceStats.rxBytes += packet->length;
1153
1154 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
1155 rxFifo.avail());
1156
1157 if (!rxEnable) {
1158 DPRINTF(Ethernet, "receive disabled...packet dropped\n");
1159 return true;
1160 }
1161
1162 if (rxFilter(packet)) {
1163 DPRINTF(Ethernet, "packet filtered...dropped\n");
1164 return true;
1165 }
1166
1167 if (rxFifo.size() >= regs.RxFifoHigh)
1168 devIntrPost(registers::Intr_RxHigh);
1169
1170 if (!rxFifo.push(packet)) {
1171 DPRINTF(Ethernet,
1172 "packet will not fit in receive buffer...packet dropped\n");
1173 return false;
1174 }
1175
1176 // If we were at the last element, back up one ot go to the new
1177 // last element of the list.
1178 if (rxFifoPtr == rxFifo.end())
1179 --rxFifoPtr;
1180
1181 devIntrPost(registers::Intr_RxPacket);
1182 rxKick();
1183 return true;
1184}
1185
1186void
1188{
1190
1191 // During drain we could have left the state machines in a waiting state and
1192 // they wouldn't get out until some other event occured to kick them.
1193 // This way they'll get out immediately
1194 txKick();
1195 rxKick();
1196}
1197
1198//=====================================================================
1199//
1200//
1201void
1203{
1204 // Serialize the PciDevice base class
1206
1210
1211 /*
1212 * Keep track of pending interrupt status.
1213 */
1216 Tick intrEventTick = 0;
1217 if (intrEvent)
1218 intrEventTick = intrEvent->when();
1219 SERIALIZE_SCALAR(intrEventTick);
1220}
1221
1222void
1224{
1225 // Unserialize the PciDevice base class
1227
1231
1232 /*
1233 * Keep track of pending interrupt status.
1234 */
1237 Tick intrEventTick;
1238 UNSERIALIZE_SCALAR(intrEventTick);
1239 if (intrEventTick) {
1240 intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); },
1241 name(), true);
1242 schedule(intrEvent, intrEventTick);
1243 }
1244}
1245
1246void
1248{
1249 int count;
1250
1251 // Serialize the PciDevice base class
1252 Base::serialize(cp);
1253
1254 if (rxState == rxCopy)
1255 panic("can't serialize with an in flight dma request rxState=%s",
1257
1258 if (txState == txCopy)
1259 panic("can't serialize with an in flight dma request txState=%s",
1261
1262 /*
1263 * Serialize the device registers that could be modified by the OS.
1264 */
1265 SERIALIZE_SCALAR(regs.Config);
1266 SERIALIZE_SCALAR(regs.IntrStatus);
1267 SERIALIZE_SCALAR(regs.IntrMask);
1268 SERIALIZE_SCALAR(regs.RxData);
1269 SERIALIZE_SCALAR(regs.TxData);
1270
1271 /*
1272 * Serialize the virtual nic state
1273 */
1274 int virtualRegsSize = virtualRegs.size();
1275 SERIALIZE_SCALAR(virtualRegsSize);
1276 for (int i = 0; i < virtualRegsSize; ++i) {
1277 const VirtualReg *vnic = &virtualRegs[i];
1278
1279 std::string reg = csprintf("vnic%d", i);
1280 paramOut(cp, reg + ".RxData", vnic->RxData);
1281 paramOut(cp, reg + ".RxDone", vnic->RxDone);
1282 paramOut(cp, reg + ".TxData", vnic->TxData);
1283 paramOut(cp, reg + ".TxDone", vnic->TxDone);
1284
1285 bool rxPacketExists = vnic->rxIndex != rxFifo.end();
1286 paramOut(cp, reg + ".rxPacketExists", rxPacketExists);
1287 if (rxPacketExists) {
1288 int rxPacket = 0;
1289 auto i = rxFifo.begin();
1290 while (i != vnic->rxIndex) {
1291 assert(i != rxFifo.end());
1292 ++i;
1293 ++rxPacket;
1294 }
1295
1296 paramOut(cp, reg + ".rxPacket", rxPacket);
1297 paramOut(cp, reg + ".rxPacketOffset", vnic->rxPacketOffset);
1298 paramOut(cp, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1299 }
1300 paramOut(cp, reg + ".rxDoneData", vnic->rxDoneData);
1301 }
1302
1303 int rxFifoPtr = -1;
1304 if (this->rxFifoPtr != rxFifo.end())
1305 rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
1307
1312
1313 VirtualList::const_iterator i, end;
1314 for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
1315 paramOut(cp, csprintf("rxList%d", count++), *i);
1316 int rxListSize = count;
1317 SERIALIZE_SCALAR(rxListSize);
1318
1319 for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)
1320 paramOut(cp, csprintf("rxBusy%d", count++), *i);
1321 int rxBusySize = count;
1322 SERIALIZE_SCALAR(rxBusySize);
1323
1324 for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
1325 paramOut(cp, csprintf("txList%d", count++), *i);
1326 int txListSize = count;
1327 SERIALIZE_SCALAR(txListSize);
1328
1329 /*
1330 * Serialize rx state machine
1331 */
1332 int rxState = this->rxState;
1333 SERIALIZE_SCALAR(rxState);
1336 rxFifo.serialize("rxFifo", cp);
1337
1338 /*
1339 * Serialize tx state machine
1340 */
1341 int txState = this->txState;
1342 SERIALIZE_SCALAR(txState);
1344 txFifo.serialize("txFifo", cp);
1345 bool txPacketExists = txPacket != nullptr;
1346 SERIALIZE_SCALAR(txPacketExists);
1347 if (txPacketExists) {
1348 txPacket->serialize("txPacket", cp);
1351 }
1352
1353 /*
1354 * If there's a pending transmit, store the time so we can
1355 * reschedule it later
1356 */
1357 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
1358 SERIALIZE_SCALAR(transmitTick);
1359}
1360
1361void
1363{
1364 // Unserialize the PciDevice base class
1366
1367 /*
1368 * Unserialize the device registers that may have been written by the OS.
1369 */
1370 UNSERIALIZE_SCALAR(regs.Config);
1371 UNSERIALIZE_SCALAR(regs.IntrStatus);
1372 UNSERIALIZE_SCALAR(regs.IntrMask);
1373 UNSERIALIZE_SCALAR(regs.RxData);
1374 UNSERIALIZE_SCALAR(regs.TxData);
1375
1380
1381 int rxListSize;
1382 UNSERIALIZE_SCALAR(rxListSize);
1383 rxList.clear();
1384 for (int i = 0; i < rxListSize; ++i) {
1385 int value;
1386 paramIn(cp, csprintf("rxList%d", i), value);
1387 rxList.push_back(value);
1388 }
1389
1390 int rxBusySize;
1391 UNSERIALIZE_SCALAR(rxBusySize);
1392 rxBusy.clear();
1393 for (int i = 0; i < rxBusySize; ++i) {
1394 int value;
1395 paramIn(cp, csprintf("rxBusy%d", i), value);
1396 rxBusy.push_back(value);
1397 }
1398
1399 int txListSize;
1400 UNSERIALIZE_SCALAR(txListSize);
1401 txList.clear();
1402 for (int i = 0; i < txListSize; ++i) {
1403 int value;
1404 paramIn(cp, csprintf("txList%d", i), value);
1405 txList.push_back(value);
1406 }
1407
1408 /*
1409 * Unserialize rx state machine
1410 */
1411 int rxState;
1415 this->rxState = (RxState) rxState;
1416 rxFifo.unserialize("rxFifo", cp);
1417
1418 int rxFifoPtr;
1420 if (rxFifoPtr >= 0) {
1421 this->rxFifoPtr = rxFifo.begin();
1422 for (int i = 0; i < rxFifoPtr; ++i)
1423 ++this->rxFifoPtr;
1424 } else {
1425 this->rxFifoPtr = rxFifo.end();
1426 }
1427
1428 /*
1429 * Unserialize tx state machine
1430 */
1431 int txState;
1434 this->txState = (TxState) txState;
1435 txFifo.unserialize("txFifo", cp);
1436 bool txPacketExists;
1437 UNSERIALIZE_SCALAR(txPacketExists);
1438 txPacket = 0;
1439 if (txPacketExists) {
1440 txPacket = std::make_shared<EthPacketData>(16384);
1441 txPacket->unserialize("txPacket", cp);
1444 }
1445
1446 /*
1447 * unserialize the virtual nic registers/state
1448 *
1449 * this must be done after the unserialization of the rxFifo
1450 * because the packet iterators depend on the fifo being populated
1451 */
1452 int virtualRegsSize;
1453 UNSERIALIZE_SCALAR(virtualRegsSize);
1454 virtualRegs.clear();
1455 virtualRegs.resize(virtualRegsSize);
1456 for (int i = 0; i < virtualRegsSize; ++i) {
1457 VirtualReg *vnic = &virtualRegs[i];
1458 std::string reg = csprintf("vnic%d", i);
1459
1460 paramIn(cp, reg + ".RxData", vnic->RxData);
1461 paramIn(cp, reg + ".RxDone", vnic->RxDone);
1462 paramIn(cp, reg + ".TxData", vnic->TxData);
1463 paramIn(cp, reg + ".TxDone", vnic->TxDone);
1464
1465 vnic->rxUnique = rxUnique++;
1466 vnic->txUnique = txUnique++;
1467
1468 bool rxPacketExists;
1469 paramIn(cp, reg + ".rxPacketExists", rxPacketExists);
1470 if (rxPacketExists) {
1471 int rxPacket;
1472 paramIn(cp, reg + ".rxPacket", rxPacket);
1473 vnic->rxIndex = rxFifo.begin();
1474 while (rxPacket--)
1475 ++vnic->rxIndex;
1476
1477 paramIn(cp, reg + ".rxPacketOffset",
1478 vnic->rxPacketOffset);
1479 paramIn(cp, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1480 } else {
1481 vnic->rxIndex = rxFifo.end();
1482 }
1483 paramIn(cp, reg + ".rxDoneData", vnic->rxDoneData);
1484 }
1485
1486 /*
1487 * If there's a pending transmit, reschedule it now
1488 */
1489 Tick transmitTick;
1490 UNSERIALIZE_SCALAR(transmitTick);
1491 if (transmitTick)
1492 schedule(txEvent, curTick() + transmitTick);
1493
1494 pioPort.sendRangeChange();
1495
1496}
1497
1498} // namespace sinic
1499} // namespace gem5
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Definition trace.hh:204
#define DPRINTF(x,...)
Definition trace.hh:210
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.
Definition types.hh:79
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)
bool dmaPending() const
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.
EtherDevBaseParams Params
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
bool sendPacket(EthPacketPtr packet)
Definition etherint.hh:73
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
Definition pktfifo.cc:87
iterator begin()
Definition pktfifo.hh:116
unsigned avail() const
Definition pktfifo.hh:104
void unserialize(const std::string &base, CheckpointIn &cp)
Definition pktfifo.cc:100
unsigned packets() const
Definition pktfifo.hh:100
EthPacketPtr front()
Definition pktfifo.hh:122
bool push(EthPacketPtr ptr)
Definition pktfifo.hh:125
bool empty() const
Definition pktfifo.hh:105
int countPacketsBefore(const_iterator i) const
Definition pktfifo.hh:186
int countPacketsAfter(const_iterator i) const
Definition pktfifo.hh:194
fifo_list::iterator iterator
Definition pktfifo.hh:85
unsigned size() const
Definition pktfifo.hh:102
void remove(iterator i)
Definition pktfifo.hh:166
iterator end()
Definition pktfifo.hh:117
void check() const
Definition pktfifo.hh:203
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
PCIConfig config
The current config space.
Definition device.hh:275
void intrClear()
Definition device.hh:365
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition device.cc:464
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition device.cc:401
Addr pciToDma(Addr pci_addr) const
Definition device.hh:359
std::array< PciBar *, 6 > BARs
Definition device.hh:308
void intrPost()
Definition device.hh:364
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
Definition io_device.hh:109
Ports are used to interface objects to each other.
Definition port.hh:62
Base(const Params &p)
Definition sinic.cc:77
void cpuIntrPost(Tick when)
Definition sinic.cc:474
EventFunctionWrapper * intrEvent
Definition sinic.hh:67
bool cpuIntrEnable
Definition sinic.hh:61
void serialize(CheckpointOut &cp) const override
Serialization stuff.
Definition sinic.cc:1202
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition sinic.cc:1223
void cpuIntrClear()
Definition sinic.cc:539
Interface * interface
Definition sinic.hh:68
bool cpuIntrPending() const
Definition sinic.cc:558
bool cpuPendingIntr
Definition sinic.hh:62
void cpuInterrupt()
Definition sinic.cc:516
EventFunctionWrapper txEvent
Definition sinic.hh:217
void transmit()
Retransmit event.
Definition sinic.cc:961
bool rxFilter(const EthPacketPtr &packet)
receive address filter
Definition sinic.cc:1138
void prepareRead(ContextID cpu, int index)
Definition sinic.cc:149
Tick write(PacketPtr pkt) override
IPR read of device register.
Definition sinic.cc:290
PacketFifo::iterator rxFifoPtr
Definition sinic.hh:181
VirtualList rxBusy
Definition sinic.hh:166
EthPacketPtr txPacket
Definition sinic.hh:191
uint64_t & regData64(Addr daddr)
Definition sinic.hh:176
VirtualList txList
Definition sinic.hh:168
void changeConfig(uint32_t newconfig)
device configuration
Definition sinic.cc:562
struct gem5::sinic::Device::@349 regs
device register file
bool recvPacket(EthPacketPtr packet)
device ethernet interface
Definition sinic.cc:1149
void devIntrPost(uint32_t interrupts)
Interrupt management.
Definition sinic.cc:404
EventFunctionWrapper txDmaEvent
Definition sinic.hh:250
void devIntrChangeMask(uint32_t newmask)
Definition sinic.cc:456
void txEventTransmit()
Definition sinic.hh:211
void prepareWrite(ContextID cpu, int index)
Definition sinic.cc:190
unsigned rxDmaLen
Definition sinic.hh:186
void rxDmaDone()
DMA parameters.
Definition sinic.cc:674
RxState
Receive State Machine States.
Definition sinic.hh:93
uint8_t * txDmaData
Definition sinic.hh:195
PacketFifo rxFifo
Definition sinic.hh:180
uint8_t * rxDmaData
Definition sinic.hh:185
Tick read(PacketPtr pkt) override
Memory Interface.
Definition sinic.cc:199
Device(const Params &p)
Definition sinic.cc:84
TxState
Transmit State Machine states.
Definition sinic.hh:103
EventFunctionWrapper rxDmaEvent
Definition sinic.hh:247
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition sinic.cc:1362
void serialize(CheckpointOut &cp) const override
Serialization stuff.
Definition sinic.cc:1247
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition sinic.cc:127
PacketFifo txFifo
Definition sinic.hh:189
void command(uint32_t command)
Definition sinic.cc:594
void resetStats() override
Callback to reset stats.
Definition sinic.cc:119
virtual void drainResume() override
Resume execution after a successful drain.
Definition sinic.cc:1187
gem5::sinic::Device::DeviceStats sinicDeviceStats
uint32_t & regData32(Addr daddr)
Definition sinic.hh:175
void prepareIO(ContextID cpu, int index)
Definition sinic.cc:136
VirtualList rxList
Definition sinic.hh:165
void devIntrClear(uint32_t interrupts=registers::Intr_All)
Definition sinic.cc:440
VirtualRegs virtualRegs
Definition sinic.hh:164
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
virtual void drainResume()
Resume execution after a successful drain.
Definition drain.hh:293
DrainState drainState() const
Return the current drain state of an object.
Definition drain.hh:324
@ Running
Running normally.
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
void squash()
Squash the current event.
Definition eventq.hh:465
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
void reschedule(Event &event, Tick when, bool always=false)
Definition eventq.hh:1030
Tick when() const
Get the time that the event is scheduled.
Definition eventq.hh:501
uint16_t cksum(const IpPtr &ptr)
Definition inet.cc:208
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
const Params & params() const
virtual void resetStats()
Callback to reset stats.
Definition group.cc:86
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 5, 0 > status
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 5, 3 > reg
Definition types.hh:92
Bitfield< 3 > exit
Definition misc.hh:883
static const int VirtualMask
Definition sinicreg.hh:69
static const int VirtualShift
Definition sinicreg.hh:68
const char * TxStateStrings[]
Definition sinic.cc:63
const char * RxStateStrings[]
Definition sinic.cc:54
const registers::Info & regInfo(Addr daddr)
Definition sinicreg.hh:192
bool regValid(Addr daddr)
Definition sinicreg.hh:234
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
int ContextID
Globally unique thread context ID.
Definition types.hh:239
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
std::shared_ptr< EthPacketData > EthPacketPtr
Definition etherpkt.hh:90
Declaration of the Packet class.
#define PCI_CMD_MSE
Definition pcireg.h:118
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
uint16_t sum() const
Definition inet.hh:747
statistics::Scalar totalVnicDistance
Definition sinic.hh:286
statistics::Scalar maxVnicDistance
Definition sinic.hh:288
statistics::Scalar numVnicDistance
Definition sinic.hh:287
DeviceStats(statistics::Group *parent)
Definition sinic.cc:103
PacketFifo::iterator rxIndex
Definition sinic.hh:147
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0