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

Generated on Wed Dec 21 2022 10:22:34 for gem5 by doxygen 1.9.1