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

Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17