sinic.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 1,617 行 · 第 1/3 页

CC
1,617
字号
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Nathan L. Binkert */#include <deque>#include <limits>#include <string>#include "arch/vtophys.hh"#include "base/inet.hh"#include "cpu/thread_context.hh"#include "cpu/intr_control.hh"#include "dev/etherlink.hh"#include "dev/sinic.hh"#include "mem/packet.hh"#include "mem/packet_access.hh"#include "sim/debug.hh"#include "sim/eventq.hh"#include "sim/host.hh"#include "sim/stats.hh"using namespace Net;using namespace TheISA;namespace Sinic {const char *RxStateStrings[] ={    "rxIdle",    "rxFifoBlock",    "rxBeginCopy",    "rxCopy",    "rxCopyDone"};const char *TxStateStrings[] ={    "txIdle",    "txFifoBlock",    "txBeginCopy",    "txCopy",    "txCopyDone"};/////////////////////////////////////////////////////////////////////////// Sinic PCI Device//Base::Base(const Params *p)    : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),      intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),      cpuPendingIntr(false), intrEvent(0), interface(NULL){}Device::Device(const Params *p)    : Base(p), rxUnique(0), txUnique(0),      virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),      rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),      rxKickTick(0), txKickTick(0),      txEvent(this), rxDmaEvent(this), txDmaEvent(this),      dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),      dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor){    interface = new Interface(name() + ".int0", this);    reset();}Device::~Device(){}voidDevice::regStats(){    rxBytes        .name(name() + ".rxBytes")        .desc("Bytes Received")        .prereq(rxBytes)        ;    rxBandwidth        .name(name() + ".rxBandwidth")        .desc("Receive Bandwidth (bits/s)")        .precision(0)        .prereq(rxBytes)        ;    rxPackets        .name(name() + ".rxPackets")        .desc("Number of Packets Received")        .prereq(rxBytes)        ;    rxPacketRate        .name(name() + ".rxPPS")        .desc("Packet Reception Rate (packets/s)")        .precision(0)        .prereq(rxBytes)        ;    rxIpPackets        .name(name() + ".rxIpPackets")        .desc("Number of IP Packets Received")        .prereq(rxBytes)        ;    rxTcpPackets        .name(name() + ".rxTcpPackets")        .desc("Number of Packets Received")        .prereq(rxBytes)        ;    rxUdpPackets        .name(name() + ".rxUdpPackets")        .desc("Number of UDP Packets Received")        .prereq(rxBytes)        ;    rxIpChecksums        .name(name() + ".rxIpChecksums")        .desc("Number of rx IP Checksums done by device")        .precision(0)        .prereq(rxBytes)        ;    rxTcpChecksums        .name(name() + ".rxTcpChecksums")        .desc("Number of rx TCP Checksums done by device")        .precision(0)        .prereq(rxBytes)        ;    rxUdpChecksums        .name(name() + ".rxUdpChecksums")        .desc("Number of rx UDP Checksums done by device")        .precision(0)        .prereq(rxBytes)        ;    totBandwidth        .name(name() + ".totBandwidth")        .desc("Total Bandwidth (bits/s)")        .precision(0)        .prereq(totBytes)        ;    totPackets        .name(name() + ".totPackets")        .desc("Total Packets")        .precision(0)        .prereq(totBytes)        ;    totBytes        .name(name() + ".totBytes")        .desc("Total Bytes")        .precision(0)        .prereq(totBytes)        ;    totPacketRate        .name(name() + ".totPPS")        .desc("Total Tranmission Rate (packets/s)")        .precision(0)        .prereq(totBytes)        ;    txBytes        .name(name() + ".txBytes")        .desc("Bytes Transmitted")        .prereq(txBytes)        ;    txBandwidth        .name(name() + ".txBandwidth")        .desc("Transmit Bandwidth (bits/s)")        .precision(0)        .prereq(txBytes)        ;    txPackets        .name(name() + ".txPackets")        .desc("Number of Packets Transmitted")        .prereq(txBytes)        ;    txPacketRate        .name(name() + ".txPPS")        .desc("Packet Tranmission Rate (packets/s)")        .precision(0)        .prereq(txBytes)        ;    txIpPackets        .name(name() + ".txIpPackets")        .desc("Number of IP Packets Transmitted")        .prereq(txBytes)        ;    txTcpPackets        .name(name() + ".txTcpPackets")        .desc("Number of TCP Packets Transmitted")        .prereq(txBytes)        ;    txUdpPackets        .name(name() + ".txUdpPackets")        .desc("Number of Packets Transmitted")        .prereq(txBytes)        ;    txIpChecksums        .name(name() + ".txIpChecksums")        .desc("Number of tx IP Checksums done by device")        .precision(0)        .prereq(txBytes)        ;    txTcpChecksums        .name(name() + ".txTcpChecksums")        .desc("Number of tx TCP Checksums done by device")        .precision(0)        .prereq(txBytes)        ;    txUdpChecksums        .name(name() + ".txUdpChecksums")        .desc("Number of tx UDP Checksums done by device")        .precision(0)        .prereq(txBytes)        ;    txBandwidth = txBytes * Stats::constant(8) / simSeconds;    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;    totBandwidth = txBandwidth + rxBandwidth;    totBytes = txBytes + rxBytes;    totPackets = txPackets + rxPackets;    txPacketRate = txPackets / simSeconds;    rxPacketRate = rxPackets / simSeconds;}EtherInt*Device::getEthPort(const std::string &if_name, int idx){    if (if_name == "interface") {        if (interface->getPeer())            panic("interface already connected to\n");        return interface;    }    return NULL;}voidDevice::prepareIO(int cpu, int index){    int size = virtualRegs.size();    if (index > size)        panic("Trying to access a vnic that doesn't exist %d > %d\n",              index, size);}voidDevice::prepareRead(int cpu, int index){    using namespace Regs;    prepareIO(cpu, index);    VirtualReg &vnic = virtualRegs[index];    // update rx registers    uint64_t rxdone = vnic.RxDone;    rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));    rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());    rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark);    rxdone = set_RxDone_NotHigh(rxdone, rxLow);    regs.RxData = vnic.RxData;    regs.RxDone = rxdone;    regs.RxWait = rxdone;    // update tx regsiters    uint64_t txdone = vnic.TxDone;    txdone = set_TxDone_Packets(txdone, txFifo.packets());    txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);    txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);    regs.TxData = vnic.TxData;    regs.TxDone = txdone;    regs.TxWait = txdone;}voidDevice::prepareWrite(int cpu, int index){    prepareIO(cpu, index);}/** * I/O read of device register */TickDevice::read(PacketPtr pkt){    assert(config.command & PCI_CMD_MSE);    assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);    int cpu = pkt->req->getCpuNum();    Addr daddr = pkt->getAddr() - BARAddrs[0];    Addr index = daddr >> Regs::VirtualShift;    Addr raddr = daddr & Regs::VirtualMask;    pkt->allocate();    if (!regValid(raddr))        panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",              cpu, index, daddr, pkt->getAddr(), pkt->getSize());    const Regs::Info &info = regInfo(raddr);    if (!info.read)        panic("read %s (write only): "              "cpu=%d vnic=%d da=%#x pa=%#x size=%d",              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());        panic("read %s (invalid size): "              "cpu=%d vnic=%d da=%#x pa=%#x size=%d",              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());    prepareRead(cpu, index);    uint64_t value = 0;    if (pkt->getSize() == 4) {        uint32_t reg = regData32(raddr);        pkt->set(reg);        value = reg;    }    if (pkt->getSize() == 8) {        uint64_t reg = regData64(raddr);        pkt->set(reg);        value = reg;    }    DPRINTF(EthernetPIO,            "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",            info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);    // reading the interrupt status register has the side effect of    // clearing it    if (raddr == Regs::IntrStatus)        devIntrClear();    return pioDelay;}/** * IPR read of device register    FaultDevice::iprRead(Addr daddr, int cpu, uint64_t &result){    if (!regValid(daddr))        panic("invalid address: da=%#x", daddr);    const Regs::Info &info = regInfo(daddr);    if (!info.read)        panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr);    DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",            info.name, cpu, daddr);    prepareRead(cpu, 0);    if (info.size == 4)        result = regData32(daddr);    if (info.size == 8)        result = regData64(daddr);    DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",            info.name, cpu, result);    return NoFault;}*//** * I/O write of device register */TickDevice::write(PacketPtr pkt){    assert(config.command & PCI_CMD_MSE);    assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);    int cpu = pkt->req->getCpuNum();    Addr daddr = pkt->getAddr() - BARAddrs[0];    Addr index = daddr >> Regs::VirtualShift;    Addr raddr = daddr & Regs::VirtualMask;    if (!regValid(raddr))        panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",                cpu, daddr, pkt->getAddr(), pkt->getSize());    const Regs::Info &info = regInfo(raddr);    if (!info.write)        panic("write %s (read only): "              "cpu=%d vnic=%d da=%#x pa=%#x size=%d",              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());    if (pkt->getSize() != info.size)        panic("write %s (invalid size): "              "cpu=%d vnic=%d da=%#x pa=%#x size=%d",              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());    VirtualReg &vnic = virtualRegs[index];    DPRINTF(EthernetPIO,            "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",            info.name, index, cpu, info.size == 4 ? pkt->get<uint32_t>() :            pkt->get<uint64_t>(), daddr, pkt->getAddr(), pkt->getSize());    prepareWrite(cpu, index);    switch (raddr) {      case Regs::Config:        changeConfig(pkt->get<uint32_t>());        break;      case Regs::Command:        command(pkt->get<uint32_t>());        break;      case Regs::IntrStatus:        devIntrClear(regs.IntrStatus & pkt->get<uint32_t>());        break;      case Regs::IntrMask:        devIntrChangeMask(pkt->get<uint32_t>());        break;      case Regs::RxData:        if (Regs::get_RxDone_Busy(vnic.RxDone))            panic("receive machine busy with another request! rxState=%s",                  RxStateStrings[rxState]);        vnic.rxUnique = rxUnique++;        vnic.RxDone = Regs::RxDone_Busy;        vnic.RxData = pkt->get<uint64_t>();        if (Regs::get_RxData_Vaddr(pkt->get<uint64_t>())) {            panic("vtophys not implemented in newmem");/*            Addr vaddr = Regs::get_RxData_Addr(reg64);            Addr paddr = vtophys(req->xc, vaddr);            DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "                    "vaddr=%#x, paddr=%#x\n",                    index, vnic.rxUnique, vaddr, paddr);            vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/        } else {            DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",                    index, vnic.rxUnique);        }        if (vnic.rxPacket == rxFifo.end()) {            DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");            rxList.push_back(index);        } else {            DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");            rxBusy.push_back(index);        }        if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {            rxState = rxFifoBlock;            rxKick();        }        break;      case Regs::TxData:        if (Regs::get_TxDone_Busy(vnic.TxDone))            panic("transmit machine busy with another request! txState=%s",                  TxStateStrings[txState]);        vnic.txUnique = txUnique++;        vnic.TxDone = Regs::TxDone_Busy;        if (Regs::get_TxData_Vaddr(pkt->get<uint64_t>())) {            panic("vtophys won't work here in newmem.\n");            /*Addr vaddr = Regs::get_TxData_Addr(reg64);            Addr paddr = vtophys(req->xc, vaddr);            DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "                    "vaddr=%#x, paddr=%#x\n",                    index, vnic.txUnique, vaddr, paddr);            vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/        } else {            DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",                    index, vnic.txUnique);        }        if (txList.empty() || txList.front() != index)            txList.push_back(index);        if (txEnable && txState == txIdle && txList.front() == index) {            txState = txFifoBlock;            txKick();        }        break;    }    return pioDelay;}void

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?