gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
51 namespace sinic
52 {
53 
54 const char *RxStateStrings[] =
55 {
56  "rxIdle",
57  "rxFifoBlock",
58  "rxBeginCopy",
59  "rxCopy",
60  "rxCopyDone"
61 };
62 
63 const 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 
101 {}
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 
118 void
120 {
122 
124 }
125 
126 Port &
127 Device::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 
135 void
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 
148 void
150 {
151  using namespace registers;
152  prepareIO(cpu, index);
153 
154  VirtualReg &vnic = virtualRegs[index];
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 
189 void
191 {
192  prepareIO(cpu, index);
193 }
194 
198 Tick
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 
289 Tick
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 
317  VirtualReg &vnic = virtualRegs[index];
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 
403 void
404 Device::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 
439 void
440 Device::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 
455 void
456 Device::devIntrChangeMask(uint32_t newmask)
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)
468  cpuIntrPost(curTick());
469  else
470  cpuIntrClear();
471 }
472 
473 void
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 
510  intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); },
511  name(), true);
513 }
514 
515 void
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 
538 void
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 
557 bool
559 { return cpuPendingIntr; }
560 
561 void
562 Device::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)
574  cpuIntrPost(curTick());
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 
593 void
595 {
596  if (command & registers::Command_Intr)
597  devIntrPost(registers::Intr_Soft);
598 
599  if (command & registers::Command_Reset)
600  reset();
601 }
602 
603 void
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 
673 void
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 
689 void
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);
805  rxMappedCount++;
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();
894  rxMappedCount--;
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 
944 void
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 
960 void
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 
1006 void
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 
1041  txState = txBeginCopy;
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);
1050  txDmaData = txPacket->data + txPacketOffset;
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 
1095  txFifo.push(txPacket);
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 
1124 void
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 
1137 bool
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 
1148 bool
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 
1186 void
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 //
1201 void
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 
1222 void
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 
1246 void
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 
1361 void
1363 {
1364  // Unserialize the PciDevice base class
1365  Base::unserialize(cp);
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
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
gem5::EtherDevBase
Dummy class to keep the Python class hierarchy in sync with the C++ object hierarchy.
Definition: etherdevice.hh:143
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:501
gem5::sinic::Device::txEvent
EventFunctionWrapper txEvent
Definition: sinic.hh:217
gem5::sinic::Base::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: sinic.cc:1223
gem5::sinic::Device::rxBeginCopy
@ rxBeginCopy
Definition: sinic.hh:96
sinic.hh
gem5::sinic::Base::txEnable
bool txEnable
Definition: sinic.hh:56
gem5::sinic::Base::cpuIntrPost
void cpuIntrPost(Tick when)
Definition: sinic.cc:474
gem5::MipsISA::misc_reg::Config
@ Config
Definition: misc.hh:112
gem5::sinic::TxStateStrings
const char * TxStateStrings[]
Definition: sinic.cc:63
gem5::PciDevice::config
PCIConfig config
The current config space.
Definition: device.hh:275
gem5::sinic::Device::rxFifo
PacketFifo rxFifo
Definition: sinic.hh:180
gem5::MipsISA::misc_reg::Count
@ Count
Definition: misc.hh:94
gem5::sinic::Device::recvPacket
bool recvPacket(EthPacketPtr packet)
device ethernet interface
Definition: sinic.cc:1149
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::sinic::Device::changeConfig
void changeConfig(uint32_t newconfig)
device configuration
Definition: sinic.cc:562
gem5::sinic::Base::cpuPendingIntr
bool cpuPendingIntr
Definition: sinic.hh:62
gem5::Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:324
gem5::PciDevice::serialize
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:401
gem5::DmaDevice::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: dma_device.cc:418
gem5::sinic::Base::serialize
void serialize(CheckpointOut &cp) const override
Serialization stuff.
Definition: sinic.cc:1202
gem5::sinic::Device::rxCopy
@ rxCopy
Definition: sinic.hh:97
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
gem5::PciDevice::unserialize
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:464
gem5::networking::cksum
uint16_t cksum(const IpPtr &ptr)
Definition: inet.cc:208
gem5::sinic::Device::DeviceStats::_maxVnicDistance
int _maxVnicDistance
Definition: sinic.hh:291
gem5::sinic::Device::DeviceStats::DeviceStats
DeviceStats(statistics::Group *parent)
Definition: sinic.cc:103
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:377
gem5::PioDevice::pioPort
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
Definition: io_device.hh:109
gem5::sinic::Device::transferDone
void transferDone()
Definition: sinic.cc:1125
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::sinic::Device::virtualRegs
VirtualRegs virtualRegs
Definition: sinic.hh:164
gem5::PciDevice::pioDelay
Tick pioDelay
Definition: device.hh:354
gem5::sinic::Base::cpuIntrClear
void cpuIntrClear()
Definition: sinic.cc:539
gem5::sinic::Device::reset
void reset()
Definition: sinic.cc:604
gem5::sinic::Device::Device
Device(const Params &p)
Definition: sinic.cc:84
gem5::sinic::Base::cpuIntrEnable
bool cpuIntrEnable
Definition: sinic.hh:61
gem5::sinic::Device::txUnique
Counter txUnique
Definition: sinic.hh:163
gem5::EtherInt::sendPacket
bool sendPacket(EthPacketPtr packet)
Definition: etherint.hh:73
gem5::sinic::Device::VirtualReg::txUnique
Counter txUnique
Definition: sinic.hh:153
gem5::sinic::Device::rxEmpty
bool rxEmpty
Definition: sinic.hh:182
gem5::sinic::Device::txCopy
@ txCopy
Definition: sinic.hh:107
gem5::sinic::Device::txPacketOffset
int txPacketOffset
Definition: sinic.hh:192
gem5::sinic::Device::resetStats
void resetStats() override
Callback to reset stats.
Definition: sinic.cc:119
gem5::DmaDevice::dmaRead
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
Definition: dma_device.hh:243
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1012
gem5::PciDevice::intrClear
void intrClear()
Definition: device.hh:365
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::sinic::registers::Info::write
bool write
Definition: sinicreg.hh:185
gem5::sinic::Device::txDmaEvent
EventFunctionWrapper txDmaEvent
Definition: sinic.hh:250
gem5::EtherDevice::EtherDeviceStats::txUdpChecksums
statistics::Scalar txUdpChecksums
Definition: etherdevice.hh:79
gem5::PacketFifo::packets
unsigned packets() const
Definition: pktfifo.hh:100
gem5::sinic::regValid
bool regValid(Addr daddr)
Definition: sinicreg.hh:234
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::statistics::Group::resetStats
virtual void resetStats()
Callback to reset stats.
Definition: group.cc:86
gem5::sinic::Device::devIntrClear
void devIntrClear(uint32_t interrupts=registers::Intr_All)
Definition: sinic.cc:440
gem5::sinic::Device::DeviceStats::numVnicDistance
statistics::Scalar numVnicDistance
Definition: sinic.hh:287
gem5::sinic::registers::Info
Definition: sinicreg.hh:181
gem5::sinic::RxStateStrings
const char * RxStateStrings[]
Definition: sinic.cc:54
gem5::sinic::Device::VirtualReg::rxPacketOffset
unsigned rxPacketOffset
Definition: sinic.hh:148
packet.hh
gem5::EtherDevice::EtherDeviceStats::txPackets
statistics::Scalar txPackets
Definition: etherdevice.hh:67
gem5::PacketFifo::begin
iterator begin()
Definition: pktfifo.hh:116
gem5::sinic::Device::txState
TxState txState
Definition: sinic.hh:188
gem5::PacketFifo::size
unsigned size() const
Definition: pktfifo.hh:102
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::sinic::Device::txDmaData
uint8_t * txDmaData
Definition: sinic.hh:195
gem5::sinic::Device::txDmaAddr
Addr txDmaAddr
Definition: sinic.hh:194
gem5::PacketFifo::unserialize
void unserialize(const std::string &base, CheckpointIn &cp)
Definition: pktfifo.cc:100
gem5::sinic::Device::regData32
uint32_t & regData32(Addr daddr)
Definition: sinic.hh:175
gem5::EtherDevice::EtherDeviceStats::txTcpChecksums
statistics::Scalar txTcpChecksums
Definition: etherdevice.hh:76
gem5::sinic::Device::rxKickTick
Tick rxKickTick
Definition: sinic.hh:202
gem5::sinic::Device::rxFilter
bool rxFilter(const EthPacketPtr &packet)
receive address filter
Definition: sinic.cc:1138
gem5::sinic::Device::txDmaLen
int txDmaLen
Definition: sinic.hh:196
stats.hh
gem5::sinic::Base::cpuIntrPending
bool cpuIntrPending() const
Definition: sinic.cc:558
gem5::sinic::Device::txIdle
@ txIdle
Definition: sinic.hh:104
gem5::auxv::Base
@ Base
Definition: aux_vector.hh:74
gem5::sinic::Device::VirtualReg::rxIndex
PacketFifo::iterator rxIndex
Definition: sinic.hh:147
gem5::sinic::Device::txDmaDone
void txDmaDone()
Definition: sinic.cc:945
gem5::sinic::Device::prepareIO
void prepareIO(ContextID cpu, int index)
Definition: sinic.cc:136
gem5::PacketFifo::end
iterator end()
Definition: pktfifo.hh:117
gem5::PacketFifo::clear
void clear()
Definition: pktfifo.hh:156
gem5::sinic::Device::TxState
TxState
Transmit State Machine states.
Definition: sinic.hh:102
gem5::sinic::Device::drainResume
virtual void drainResume() override
Resume execution after a successful drain.
Definition: sinic.cc:1187
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::sinic::Device::txBeginCopy
@ txBeginCopy
Definition: sinic.hh:106
gem5::EthPacketPtr
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:90
gem5::sinic::Device::VirtualReg::RxData
uint64_t RxData
Definition: sinic.hh:142
gem5::SimObject::params
const Params & params() const
Definition: sim_object.hh:176
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::X86ISA::count
count
Definition: misc.hh:710
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::sinic::Device::RxState
RxState
Receive State Machine States.
Definition: sinic.hh:92
gem5::sinic::Device::rxUnique
Counter rxUnique
Definition: sinic.hh:162
gem5::sinic::Device::sinicDeviceStats
gem5::sinic::Device::DeviceStats sinicDeviceStats
gem5::networking::IpPtr
Definition: inet.hh:356
gem5::DmaDevice::dmaPending
bool dmaPending() const
Definition: dma_device.hh:256
gem5::EtherDevice::etherDeviceStats
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
gem5::sinic::Device::txKick
void txKick()
Definition: sinic.cc:1007
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::sinic::Device::txFifoBlock
@ txFifoBlock
Definition: sinic.hh:105
gem5::statistics::reset
void reset()
Definition: statistics.cc:309
gem5::EtherDevice::EtherDeviceStats::rxIpChecksums
statistics::Scalar rxIpChecksums
Definition: etherdevice.hh:74
gem5::sinic::Device::VirtualReg
Definition: sinic.hh:140
gem5::PciDevice::BARs
std::array< PciBar *, 6 > BARs
Definition: device.hh:308
gem5::sinic::Device::DeviceStats::maxVnicDistance
statistics::Scalar maxVnicDistance
Definition: sinic.hh:288
gem5::sinic::registers::Info::name
const char * name
Definition: sinicreg.hh:186
gem5::sinic::Device::txList
VirtualList txList
Definition: sinic.hh:168
gem5::sinic::Device::~Device
~Device()
Definition: sinic.cc:100
debug.hh
gem5::DmaDevice::Params
DmaDeviceParams Params
Definition: dma_device.hh:224
gem5::PacketFifo::remove
void remove(iterator i)
Definition: pktfifo.hh:166
gem5::EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1030
gem5::DmaDevice::dmaWrite
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
Definition: dma_device.hh:229
gem5::EtherDevice::EtherDeviceStats::rxUdpChecksums
statistics::Scalar rxUdpChecksums
Definition: etherdevice.hh:80
compiler.hh
gem5::sinic::Device::txPacket
EthPacketPtr txPacket
Definition: sinic.hh:191
gem5::PacketFifo::front
EthPacketPtr front()
Definition: pktfifo.hh:122
gem5::sinic::Device::rxCopyDone
@ rxCopyDone
Definition: sinic.hh:98
gem5::sinic::Device::rxList
VirtualList rxList
Definition: sinic.hh:165
gem5::sinic::Base::interface
Interface * interface
Definition: sinic.hh:68
gem5::sinic::Device::rxDmaDone
void rxDmaDone()
DMA parameters.
Definition: sinic.cc:674
gem5::sinic::Device::rxDmaData
uint8_t * rxDmaData
Definition: sinic.hh:185
gem5::PacketFifo::push
bool push(EthPacketPtr ptr)
Definition: pktfifo.hh:125
gem5::sinic::Device::regs
struct gem5::sinic::Device::@337 regs
device register file
gem5::EtherDevice::EtherDeviceStats::rxBytes
statistics::Scalar rxBytes
Definition: etherdevice.hh:65
gem5::sinic::registers::VirtualMask
static const int VirtualMask
Definition: sinicreg.hh:69
gem5::igbreg::txd_op::ip
bool ip(TxDesc *d)
Definition: i8254xGBe_defs.hh:330
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::sinic::Device::devIntrPost
void devIntrPost(uint32_t interrupts)
Interrupt management.
Definition: sinic.cc:404
gem5::sinic::Device::rxKick
void rxKick()
Definition: sinic.cc:690
gem5::sinic::Device::write
Tick write(PacketPtr pkt) override
IPR read of device register.
Definition: sinic.cc:290
gem5::sinic::Device::txFull
bool txFull
Definition: sinic.hh:190
gem5::PacketFifo::iterator
fifo_list::iterator iterator
Definition: pktfifo.hh:85
gem5::sinic::Base
Definition: sinic.hh:52
name
const std::string & name()
Definition: trace.cc:48
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
gem5::sinic::Device::rxDmaAddr
Addr rxDmaAddr
Definition: sinic.hh:184
gem5::X86ISA::exit
Bitfield< 3 > exit
Definition: misc.hh:855
DDUMP
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
Definition: trace.hh:204
packet_access.hh
gem5::Clocked::clockEdge
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...
Definition: clocked_object.hh:177
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::sinic::Device::rxMappedCount
int rxMappedCount
Definition: sinic.hh:171
gem5::sinic::Device::devIntrChangeMask
void devIntrChangeMask(uint32_t newmask)
Definition: sinic.cc:456
gem5::EventFunctionWrapper
Definition: eventq.hh:1136
gem5::sinic::Device::txKickTick
Tick txKickTick
Definition: sinic.hh:205
gem5::sinic::Base::cpuInterrupt
void cpuInterrupt()
Definition: sinic.cc:516
gem5::sinic::Device::rxActive
int rxActive
Definition: sinic.hh:167
gem5::sinic::Device::txCopyDone
@ txCopyDone
Definition: sinic.hh:108
gem5::sinic::Device::rxBusy
VirtualList rxBusy
Definition: sinic.hh:166
PCI_CMD_MSE
#define PCI_CMD_MSE
Definition: pcireg.h:118
gem5::Drainable::drainResume
virtual void drainResume()
Resume execution after a successful drain.
Definition: drain.hh:293
gem5::sinic::Device::VirtualReg::TxDone
uint64_t TxDone
Definition: sinic.hh:145
gem5::paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
gem5::sinic::Device::regData64
uint64_t & regData64(Addr daddr)
Definition: sinic.hh:176
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
types.hh
gem5::sinic::Device::rxLow
bool rxLow
Definition: sinic.hh:183
gem5::sinic::Device::rxState
RxState rxState
Definition: sinic.hh:179
gem5::PacketFifo::countPacketsBefore
int countPacketsBefore(const_iterator i) const
Definition: pktfifo.hh:186
gem5::sinic::Device::read
Tick read(PacketPtr pkt) override
Memory Interface.
Definition: sinic.cc:199
gem5::sinic::registers::VirtualShift
static const int VirtualShift
Definition: sinicreg.hh:68
gem5::EtherDevice::EtherDeviceStats::rxPackets
statistics::Scalar rxPackets
Definition: etherdevice.hh:68
gem5::paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
gem5::ContextID
int ContextID
Globally unique thread context ID.
Definition: types.hh:239
gem5::EtherDevice::EtherDeviceStats::txBytes
statistics::Scalar txBytes
Definition: etherdevice.hh:64
gem5::PacketFifo::avail
unsigned avail() const
Definition: pktfifo.hh:104
gem5::sinic::Device::prepareRead
void prepareRead(ContextID cpu, int index)
Definition: sinic.cc:149
gem5::sinic::Device::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: sinic.cc:1362
gem5::sinic::Device::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: sinic.cc:127
gem5::sinic::Device::VirtualReg::rxUnique
Counter rxUnique
Definition: sinic.hh:152
gem5::statistics::Group
Statistics container.
Definition: group.hh:92
gem5::sinic::Device::rxFifoPtr
PacketFifo::iterator rxFifoPtr
Definition: sinic.hh:181
gem5::sinic::Base::intrTick
Tick intrTick
Definition: sinic.hh:60
gem5::EtherDevice::EtherDeviceStats::rxTcpChecksums
statistics::Scalar rxTcpChecksums
Definition: etherdevice.hh:77
gem5::Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:78
gem5::sinic::registers::Info::read
bool read
Definition: sinicreg.hh:184
gem5::sinic::Device::VirtualReg::RxDone
uint64_t RxDone
Definition: sinic.hh:143
gem5::sinic::Device::prepareWrite
void prepareWrite(ContextID cpu, int index)
Definition: sinic.cc:190
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::sinic::Device::serialize
void serialize(CheckpointOut &cp) const override
Serialization stuff.
Definition: sinic.cc:1247
gem5::sinic::Device::rxFifoBlock
@ rxFifoBlock
Definition: sinic.hh:95
gem5::sinic::Base::intrEvent
EventFunctionWrapper * intrEvent
Definition: sinic.hh:67
gem5::networking::UdpHdr::sum
uint16_t sum() const
Definition: inet.hh:747
gem5::sinic::Device::rxDmaLen
unsigned rxDmaLen
Definition: sinic.hh:186
gem5::Event::squash
void squash()
Squash the current event.
Definition: eventq.hh:465
gem5::PacketFifo::countPacketsAfter
int countPacketsAfter(const_iterator i) const
Definition: pktfifo.hh:194
gem5::Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:108
gem5::sinic::regInfo
const registers::Info & regInfo(Addr daddr)
Definition: sinicreg.hh:192
gem5::DrainState::Running
@ Running
Running normally.
gem5::sinic::registers::Info::size
uint8_t size
Definition: sinicreg.hh:183
gem5::sinic::Device::txEventTransmit
void txEventTransmit()
Definition: sinic.hh:211
gem5::PciDevice::pciToDma
Addr pciToDma(Addr pci_addr) const
Definition: device.hh:359
gem5::sinic::Device::DeviceStats::totalVnicDistance
statistics::Scalar totalVnicDistance
Definition: sinic.hh:286
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:807
gem5::sinic::Device::VirtualReg::rxDoneData
uint64_t rxDoneData
Definition: sinic.hh:150
gem5::sinic::Device::transmit
void transmit()
Retransmit event.
Definition: sinic.cc:961
inet.hh
gem5::sinic::Device::rxBusyCount
int rxBusyCount
Definition: sinic.hh:170
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::PciDevice::intrPost
void intrPost()
Definition: device.hh:364
gem5::sinic::Base::intrDelay
Tick intrDelay
Definition: sinic.hh:59
gem5::PacketFifo::pop
void pop()
Definition: pktfifo.hh:143
gem5::sinic::Device::rxIdle
@ rxIdle
Definition: sinic.hh:94
gem5::networking::UdpPtr
Definition: inet.hh:759
gem5::sinic::Device::rxDirtyCount
int rxDirtyCount
Definition: sinic.hh:172
gem5::sinic::Device::command
void command(uint32_t command)
Definition: sinic.cc:594
gem5::sinic::Device::txPacketBytes
int txPacketBytes
Definition: sinic.hh:193
gem5::sinic::Device::VirtualReg::rxPacketBytes
unsigned rxPacketBytes
Definition: sinic.hh:149
gem5::sinic::Device::VirtualReg::TxData
uint64_t TxData
Definition: sinic.hh:144
gem5::sinic::Device::rxDmaEvent
EventFunctionWrapper rxDmaEvent
Definition: sinic.hh:247
gem5::igbreg::txd_op::tcp
bool tcp(TxDesc *d)
Definition: i8254xGBe_defs.hh:336
gem5::PacketFifo::empty
bool empty() const
Definition: pktfifo.hh:105
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
gem5::PacketFifo::check
void check() const
Definition: pktfifo.hh:203
gem5::EtherDevice::EtherDeviceStats::txIpChecksums
statistics::Scalar txIpChecksums
Definition: etherdevice.hh:73
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:458
gem5::networking::TcpPtr
Definition: inet.hh:645
gem5::PacketFifo::serialize
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
Definition: pktfifo.cc:87
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:480
gem5::sinic::Base::rxEnable
bool rxEnable
Definition: sinic.hh:55
gem5::sinic::Device::txFifo
PacketFifo txFifo
Definition: sinic.hh:189
eventq.hh

Generated on Sun Jul 30 2023 01:56:56 for gem5 by doxygen 1.8.17