Devices: Make EtherInts connect in the same way memory ports currently do.

--HG--
extra : convert_revision : 765b096785a77df9adc4791c9101b90696bd7be2
This commit is contained in:
Ali Saidi 2007-08-16 16:49:02 -04:00
parent a9e4daf574
commit 773cb77656
21 changed files with 393 additions and 147 deletions

View file

@ -42,7 +42,6 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
class BaseTsunami(Tsunami): class BaseTsunami(Tsunami):
ethernet = NSGigE(configdata=NSGigEPciData(), ethernet = NSGigE(configdata=NSGigEPciData(),
pci_bus=0, pci_dev=1, pci_func=0) pci_bus=0, pci_dev=1, pci_func=0)
etherint = NSGigEInt(device=Parent.ethernet)
ide = IdeController(disks=[Parent.disk0, Parent.disk2], ide = IdeController(disks=[Parent.disk0, Parent.disk2],
pci_func=0, pci_dev=0, pci_bus=0) pci_func=0, pci_dev=0, pci_bus=0)
@ -125,8 +124,10 @@ def makeDualRoot(testSystem, driveSystem, dumpfile):
self = Root() self = Root()
self.testsys = testSystem self.testsys = testSystem
self.drivesys = driveSystem self.drivesys = driveSystem
self.etherlink = EtherLink(int1 = Parent.testsys.tsunami.etherint[0], self.etherlink = EtherLink()
int2 = Parent.drivesys.tsunami.etherint[0]) self.etherlink.int0 = Parent.testsys.tsunami.ethernet.interface
self.etherlink.int1 = Parent.drivesys.tsunami.ethernet.interface
if dumpfile: if dumpfile:
self.etherdump = EtherDump(file=dumpfile) self.etherdump = EtherDump(file=dumpfile)
self.etherlink.dump = Parent.etherdump self.etherlink.dump = Parent.etherdump

View file

@ -31,27 +31,26 @@ from m5.params import *
from m5.proxy import * from m5.proxy import *
from Pci import PciDevice, PciConfigData from Pci import PciDevice, PciConfigData
class EtherInt(SimObject): class EtherObject(SimObject):
type = 'EtherInt' type = 'EtherObject'
abstract = True abstract = True
peer = Param.EtherInt(NULL, "peer interface")
class EtherLink(SimObject): class EtherLink(EtherObject):
type = 'EtherLink' type = 'EtherLink'
int1 = Param.EtherInt("interface 1") int0 = Port("interface 0")
int2 = Param.EtherInt("interface 2") int1 = Port("interface 1")
delay = Param.Latency('0us', "packet transmit delay") delay = Param.Latency('0us', "packet transmit delay")
delay_var = Param.Latency('0ns', "packet transmit delay variability") delay_var = Param.Latency('0ns', "packet transmit delay variability")
speed = Param.NetworkBandwidth('1Gbps', "link speed") speed = Param.NetworkBandwidth('1Gbps', "link speed")
dump = Param.EtherDump(NULL, "dump object") dump = Param.EtherDump(NULL, "dump object")
class EtherBus(SimObject): class EtherBus(EtherObject):
type = 'EtherBus' type = 'EtherBus'
loopback = Param.Bool(True, "send packet back to the sending interface") loopback = Param.Bool(True, "send packet back to the sending interface")
dump = Param.EtherDump(NULL, "dump object") dump = Param.EtherDump(NULL, "dump object")
speed = Param.NetworkBandwidth('100Mbps', "bus speed in bits per second") speed = Param.NetworkBandwidth('100Mbps', "bus speed in bits per second")
class EtherTap(EtherInt): class EtherTap(EtherObject):
type = 'EtherTap' type = 'EtherTap'
bufsz = Param.Int(10000, "tap buffer size") bufsz = Param.Int(10000, "tap buffer size")
dump = Param.EtherDump(NULL, "dump object") dump = Param.EtherDump(NULL, "dump object")
@ -62,7 +61,12 @@ class EtherDump(SimObject):
file = Param.String("dump file") file = Param.String("dump file")
maxlen = Param.Int(96, "max portion of packet data to dump") maxlen = Param.Int(96, "max portion of packet data to dump")
class IGbE(PciDevice): class EtherDevice(PciDevice):
type = 'EtherDevice'
abstract = True
interface = Port("Ethernet Interrface")
class IGbE(EtherDevice):
type = 'IGbE' type = 'IGbE'
hardware_address = Param.EthernetAddr(NextEthernetAddr, hardware_address = Param.EthernetAddr(NextEthernetAddr,
"Ethernet Hardware Address") "Ethernet Hardware Address")
@ -97,11 +101,7 @@ class IGbEPciData(PciConfigData):
InterruptPin = 0x01 InterruptPin = 0x01
BAR0Size = '128kB' BAR0Size = '128kB'
class IGbEInt(EtherInt): class EtherDevBase(EtherDevice):
type = 'IGbEInt'
device = Param.IGbE("Ethernet device of this interface")
class EtherDevBase(PciDevice):
type = 'EtherDevBase' type = 'EtherDevBase'
abstract = True abstract = True
hardware_address = Param.EthernetAddr(NextEthernetAddr, hardware_address = Param.EthernetAddr(NextEthernetAddr,
@ -155,10 +155,6 @@ class NSGigE(EtherDevBase):
configdata = NSGigEPciData() configdata = NSGigEPciData()
class NSGigEInt(EtherInt):
type = 'NSGigEInt'
device = Param.NSGigE("Ethernet device of this interface")
class SinicPciData(PciConfigData): class SinicPciData(PciConfigData):
VendorID = 0x1291 VendorID = 0x1291
DeviceID = 0x1293 DeviceID = 0x1293
@ -197,9 +193,3 @@ class Sinic(EtherDevBase):
configdata = SinicPciData() configdata = SinicPciData()
class SinicInt(EtherInt):
type = 'SinicInt'
cxx_namespace = 'Sinic'
cxx_class = 'Interface'
device = Param.Sinic("Ethernet device of this interface")

View file

@ -47,10 +47,9 @@
using namespace std; using namespace std;
EtherBus::EtherBus(const string &name, double speed, bool loop, EtherBus::EtherBus(const Params *p)
EtherDump *packet_dump) : EtherObject(p), ticksPerByte(p->speed), loopback(p->loopback),
: SimObject(name), ticksPerByte(speed), loopback(loop), event(&mainEventQueue, this), sender(0), dump(p->dump)
event(&mainEventQueue, this), sender(0), dump(packet_dump)
{ {
} }
@ -78,9 +77,11 @@ EtherBus::txDone()
packet = 0; packet = 0;
} }
void EtherInt*
EtherBus::reg(EtherInt *dev) EtherBus::getEthPort(const std::string &if_name, int idx)
{ devlist.push_back(dev); } {
panic("Etherbus doesn't work\n");
}
bool bool
EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt) EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
@ -106,5 +107,5 @@ EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
EtherBus * EtherBus *
EtherBusParams::create() EtherBusParams::create()
{ {
return new EtherBus(name, speed, loopback, dump); return new EtherBus(this);
} }

View file

@ -37,11 +37,13 @@
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "dev/etherobject.hh"
#include "params/EtherBus.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
class EtherDump; class EtherDump;
class EtherInt; class EtherInt;
class EtherBus : public SimObject class EtherBus : public EtherObject
{ {
protected: protected:
typedef std::list<EtherInt *> devlist_t; typedef std::list<EtherInt *> devlist_t;
@ -68,14 +70,21 @@ class EtherBus : public SimObject
EtherDump *dump; EtherDump *dump;
public: public:
EtherBus(const std::string &name, double speed, bool loopback, typedef EtherBusParams Params;
EtherDump *dump); EtherBus(const Params *p);
virtual ~EtherBus() {} virtual ~EtherBus() {}
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
void txDone(); void txDone();
void reg(EtherInt *dev); void reg(EtherInt *dev);
bool busy() const { return (bool)packet; } bool busy() const { return (bool)packet; }
bool send(EtherInt *sender, EthPacketPtr &packet); bool send(EtherInt *sender, EthPacketPtr &packet);
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
}; };
#endif // __ETHERBUS_H__ #endif // __ETHERBUS_H__

69
src/dev/etherdevice.hh Normal file
View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
/**
* @file
* Base Ethernet Device declaration.
*/
#ifndef __DEV_ETHERDEVICE_HH__
#define __DEV_ETHERDEVICE_HH__
#include "dev/pcidev.hh"
#include "params/EtherDevice.hh"
#include "sim/sim_object.hh"
class EtherInt;
/**
* The base EtherObject class, allows for an accesor function to a
* simobj that returns the Port.
*/
class EtherDevice : public PciDev
{
public:
typedef EtherDeviceParams Params;
EtherDevice(const Params *params)
: PciDev(params)
{}
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
public:
/** Additional function to return the Port of a memory object. */
virtual EtherInt *getEthPort(const std::string &if_name, int idx = -1) = 0;
};
#endif //__DEV_ETHERDEVICE_HH__

View file

@ -39,23 +39,28 @@
#include <string> #include <string>
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "sim/sim_object.hh"
/* /*
* Class representing the actual interface between two ethernet * Class representing the actual interface between two ethernet
* components. These components are intended to attach to another * components. These components are intended to attach to another
* ethernet interface on one side and whatever device on the other. * ethernet interface on one side and whatever device on the other.
*/ */
class EtherInt : public SimObject class EtherInt
{ {
protected: protected:
mutable std::string portName;
EtherInt *peer; EtherInt *peer;
public: public:
EtherInt(const std::string &name) : SimObject(name), peer(NULL) {} EtherInt(const std::string &name)
: portName(name), peer(NULL) {}
virtual ~EtherInt() {} virtual ~EtherInt() {}
/** Return port name (for DPRINTF). */
const std::string &name() const { return portName; }
void setPeer(EtherInt *p); void setPeer(EtherInt *p);
EtherInt* getPeer() { return peer; }
void recvDone() { peer->sendDone(); } void recvDone() { peer->sendDone(); }
virtual void sendDone() = 0; virtual void sendDone() = 0;

View file

@ -51,22 +51,19 @@
using namespace std; using namespace std;
EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, EtherLink::EtherLink(const Params *p)
double rate, Tick delay, Tick delayVar, EtherDump *dump) : EtherObject(p)
: SimObject(name)
{ {
link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); link[0] = new Link(name() + ".link0", this, 0, params()->speed,
link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); params()->delay, params()->delay_var, params()->dump);
link[1] = new Link(name() + ".link1", this, 1, params()->speed,
params()->delay, params()->delay_var, params()->dump);
interface[0] = new Interface(name + ".int0", link[0], link[1]); interface[0] = new Interface(name() + ".int0", link[0], link[1]);
interface[1] = new Interface(name + ".int1", link[1], link[0]); interface[1] = new Interface(name() + ".int1", link[1], link[0]);
interface[0]->setPeer(peer0);
peer0->setPeer(interface[0]);
interface[1]->setPeer(peer1);
peer1->setPeer(interface[1]);
} }
EtherLink::~EtherLink() EtherLink::~EtherLink()
{ {
delete link[0]; delete link[0];
@ -76,6 +73,23 @@ EtherLink::~EtherLink()
delete interface[1]; delete interface[1];
} }
EtherInt*
EtherLink::getEthPort(const std::string &if_name, int idx)
{
Interface *i;
if (if_name == "int0")
i = interface[0];
else if (if_name == "int1")
i = interface[1];
else
return NULL;
if (i->getPeer())
panic("interface already connected to\n");
return i;
}
EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
: EtherInt(name), txlink(tx) : EtherInt(name), txlink(tx)
{ {
@ -275,5 +289,5 @@ REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
EtherLink * EtherLink *
EtherLinkParams::create() EtherLinkParams::create()
{ {
return new EtherLink(name, int1, int2, speed, delay, delay_var, dump); return new EtherLink(this);
} }

View file

@ -35,8 +35,10 @@
#ifndef __DEV_ETHERLINK_HH__ #ifndef __DEV_ETHERLINK_HH__
#define __DEV_ETHERLINK_HH__ #define __DEV_ETHERLINK_HH__
#include "dev/etherobject.hh"
#include "dev/etherint.hh" #include "dev/etherint.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "params/EtherLink.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "sim/host.hh" #include "sim/host.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
@ -46,7 +48,7 @@ class Checkpoint;
/* /*
* Model for a fixed bandwidth full duplex ethernet link * Model for a fixed bandwidth full duplex ethernet link
*/ */
class EtherLink : public SimObject class EtherLink : public EtherObject
{ {
protected: protected:
class Interface; class Interface;
@ -118,13 +120,21 @@ class EtherLink : public SimObject
}; };
Link *link[2]; Link *link[2];
EtherInt *interface[2]; Interface *interface[2];
public: public:
EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1, typedef EtherLinkParams Params;
double rate, Tick delay, Tick delayVar, EtherDump *dump); EtherLink(const Params *p);
virtual ~EtherLink(); virtual ~EtherLink();
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);

67
src/dev/etherobject.hh Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
/**
* @file
* Base Ethernet Object declaration.
*/
#ifndef __DEV_ETHEROBJECT_HH__
#define __DEV_ETHEROBJECT_HH__
#include "params/EtherObject.hh"
#include "sim/sim_object.hh"
class EtherInt;
/**
* The base EtherObject class, allows for an accesor function to a
* simobj that returns the Port.
*/
class EtherObject : public SimObject
{
public:
typedef EtherObjectParams Params;
EtherObject(const Params *params)
: SimObject(params) {}
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
public:
/** Additional function to return the Port of a memory object. */
virtual EtherInt *getEthPort(const std::string &if_name, int idx = -1) = 0;
};
#endif //__MEM_MEM_OBJECT_HH__

View file

@ -69,11 +69,17 @@ class EthPacketData : public RefCounted
int slack; int slack;
public: public:
EthPacketData() : data(NULL), length(0), slack(0) { } EthPacketData() : data(NULL), length(0), slack(0)
{ }
explicit EthPacketData(size_t size) explicit EthPacketData(size_t size)
: data(new uint8_t[size]), length(0), slack(0) { } : data(new uint8_t[size]), length(0), slack(0)
{ }
EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0) EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
: data(d.release()), length(l), slack(s) { } : data(d.release()), length(l), slack(s)
{ }
~EthPacketData() { if (data) delete [] data; } ~EthPacketData() { if (data) delete [] data; }
public: public:

View file

@ -50,7 +50,6 @@
#include "dev/etherint.hh" #include "dev/etherint.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "dev/ethertap.hh" #include "dev/ethertap.hh"
#include "params/EtherTap.hh"
using namespace std; using namespace std;
@ -127,13 +126,14 @@ class TapEvent : public PollEvent
virtual void process(int revent) { tap->process(revent); } virtual void process(int revent) { tap->process(revent); }
}; };
EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz) EtherTap::EtherTap(const Params *p)
: EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d), : EtherObject(p), event(NULL), socket(-1), buflen(p->bufsz), dump(p->dump),
txEvent(this) interface(NULL), txEvent(this)
{ {
buffer = new char[buflen]; buffer = new char[buflen];
listener = new TapListener(this, port); listener = new TapListener(this, p->port);
listener->listen(); listener->listen();
interface = new EtherTapInt(name() + ".interface", this);
} }
EtherTap::~EtherTap() EtherTap::~EtherTap()
@ -182,7 +182,7 @@ EtherTap::recvPacket(EthPacketPtr packet)
write(socket, &len, sizeof(len)); write(socket, &len, sizeof(len));
write(socket, packet->data, packet->length); write(socket, packet->data, packet->length);
recvDone(); interface->recvDone();
return true; return true;
} }
@ -235,7 +235,7 @@ EtherTap::process(int revent)
DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length); DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
DDUMP(EthernetData, packet->data, packet->length); DDUMP(EthernetData, packet->data, packet->length);
if (!sendPacket(packet)) { if (!interface->sendPacket(packet)) {
DPRINTF(Ethernet, "bus busy...buffer for retransmission\n"); DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
packetBuffer.push(packet); packetBuffer.push(packet);
if (!txEvent.scheduled()) if (!txEvent.scheduled())
@ -253,7 +253,7 @@ EtherTap::retransmit()
return; return;
EthPacketPtr packet = packetBuffer.front(); EthPacketPtr packet = packetBuffer.front();
if (sendPacket(packet)) { if (interface->sendPacket(packet)) {
if (dump) if (dump)
dump->dump(packet); dump->dump(packet);
DPRINTF(Ethernet, "EtherTap retransmit\n"); DPRINTF(Ethernet, "EtherTap retransmit\n");
@ -265,6 +265,18 @@ EtherTap::retransmit()
txEvent.schedule(curTick + retryTime); txEvent.schedule(curTick + retryTime);
} }
EtherInt*
EtherTap::getEthPort(const std::string &if_name, int idx)
{
if (if_name == "tap") {
if (interface->getPeer())
panic("Interface already connected to\n");
return interface;
}
return NULL;
}
//===================================================================== //=====================================================================
void void
@ -316,12 +328,5 @@ EtherTap::unserialize(Checkpoint *cp, const std::string &section)
EtherTap * EtherTap *
EtherTapParams::create() EtherTapParams::create()
{ {
EtherTap *tap = new EtherTap(name, dump, port, bufsz); return new EtherTap(this);
if (peer) {
tap->setPeer(peer);
peer->setPeer(tap);
}
return tap;
} }

View file

@ -38,19 +38,22 @@
#include <queue> #include <queue>
#include <string> #include <string>
#include "base/pollevent.hh"
#include "dev/etherobject.hh"
#include "dev/etherint.hh" #include "dev/etherint.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "params/EtherTap.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "base/pollevent.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
class TapEvent; class TapEvent;
class TapListener; class TapListener;
class EtherTapInt;
/* /*
* Interface to connect a simulated ethernet device to the real world * Interface to connect a simulated ethernet device to the real world
*/ */
class EtherTap : public EtherInt class EtherTap : public EtherObject
{ {
protected: protected:
friend class TapEvent; friend class TapEvent;
@ -73,6 +76,7 @@ class EtherTap : public EtherInt
protected: protected:
std::string device; std::string device;
std::queue<EthPacketPtr> packetBuffer; std::queue<EthPacketPtr> packetBuffer;
EtherTapInt *interface;
void process(int revent); void process(int revent);
void enqueue(EthPacketData *packet); void enqueue(EthPacketData *packet);
@ -96,9 +100,18 @@ class EtherTap : public EtherInt
TxEvent txEvent; TxEvent txEvent;
public: public:
EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz); typedef EtherTapParams Params;
EtherTap(const Params *p);
virtual ~EtherTap(); virtual ~EtherTap();
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
virtual bool recvPacket(EthPacketPtr packet); virtual bool recvPacket(EthPacketPtr packet);
virtual void sendDone(); virtual void sendDone();
@ -106,4 +119,18 @@ class EtherTap : public EtherInt
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };
class EtherTapInt : public EtherInt
{
private:
EtherTap *tap;
public:
EtherTapInt(const std::string &name, EtherTap *t)
: EtherInt(name), tap(t)
{ }
virtual bool recvPacket(EthPacketPtr pkt) { return tap->recvPacket(pkt); }
virtual void sendDone() { tap->sendDone(); }
};
#endif // __ETHERTAP_HH__ #endif // __ETHERTAP_HH__

View file

@ -48,21 +48,22 @@
#include "mem/packet.hh" #include "mem/packet.hh"
#include "mem/packet_access.hh" #include "mem/packet_access.hh"
#include "params/IGbE.hh" #include "params/IGbE.hh"
#include "params/IGbEInt.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
#include "sim/system.hh" #include "sim/system.hh"
using namespace iGbReg; using namespace iGbReg;
using namespace Net; using namespace Net;
IGbE::IGbE(Params *p) IGbE::IGbE(const Params *p)
: PciDev(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control), : EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control),
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
txTick(false), txFifoTick(false), rdtrEvent(this), radvEvent(this), txTick(false), txFifoTick(false), rdtrEvent(this), radvEvent(this),
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this), tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size), rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock) txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock)
{ {
etherInt = new IGbEInt(name() + ".int", this);
// Initialized internal registers per Intel documentation // Initialized internal registers per Intel documentation
// All registers intialized to 0 by per register constructor // All registers intialized to 0 by per register constructor
regs.ctrl.fd(1); regs.ctrl.fd(1);
@ -108,6 +109,17 @@ IGbE::IGbE(Params *p)
txFifo.clear(); txFifo.clear();
} }
EtherInt*
IGbE::getEthPort(const std::string &if_name, int idx)
{
if (if_name == "interface" && !etherInt) {
if (etherInt->getPeer())
panic("Port already connected to\n");
return etherInt;
}
return NULL;
}
Tick Tick
IGbE::writeConfig(PacketPtr pkt) IGbE::writeConfig(PacketPtr pkt)
@ -1447,20 +1459,6 @@ IGbE::unserialize(Checkpoint *cp, const std::string &section)
rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section)); rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section));
} }
IGbEInt *
IGbEIntParams::create()
{
IGbEInt *dev_int = new IGbEInt(name, device);
EtherInt *p = (EtherInt *)peer;
if (p) {
dev_int->setPeer(p);
p->setPeer(dev_int);
}
return dev_int;
}
IGbE * IGbE *
IGbEParams::create() IGbEParams::create()
{ {

View file

@ -40,6 +40,7 @@
#include "base/inet.hh" #include "base/inet.hh"
#include "base/statistics.hh" #include "base/statistics.hh"
#include "dev/etherdevice.hh"
#include "dev/etherint.hh" #include "dev/etherint.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "dev/i8254xGBe_defs.hh" #include "dev/i8254xGBe_defs.hh"
@ -50,7 +51,7 @@
class IGbEInt; class IGbEInt;
class IGbE : public PciDev class IGbE : public EtherDevice
{ {
private: private:
IGbEInt *etherInt; IGbEInt *etherInt;
@ -592,9 +593,11 @@ class IGbE : public PciDev
{ {
return dynamic_cast<const Params *>(_params); return dynamic_cast<const Params *>(_params);
} }
IGbE(Params *params); IGbE(const Params *params);
~IGbE() {} ~IGbE() {}
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
Tick clock; Tick clock;
inline Tick cycles(int numCycles) const { return numCycles * clock; } inline Tick cycles(int numCycles) const { return numCycles * clock; }
@ -606,8 +609,6 @@ class IGbE : public PciDev
bool ethRxPkt(EthPacketPtr packet); bool ethRxPkt(EthPacketPtr packet);
void ethTxDone(); void ethTxDone();
void setEthInt(IGbEInt *i) { assert(!etherInt); etherInt = i; }
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual unsigned int drain(Event *de); virtual unsigned int drain(Event *de);
@ -623,7 +624,7 @@ class IGbEInt : public EtherInt
public: public:
IGbEInt(const std::string &name, IGbE *d) IGbEInt(const std::string &name, IGbE *d)
: EtherInt(name), dev(d) : EtherInt(name), dev(d)
{ dev->setEthInt(this); } { }
virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); } virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
virtual void sendDone() { dev->ethTxDone(); } virtual void sendDone() { dev->ethTxDone(); }

View file

@ -44,7 +44,6 @@
#include "mem/packet.hh" #include "mem/packet.hh"
#include "mem/packet_access.hh" #include "mem/packet_access.hh"
#include "params/NSGigE.hh" #include "params/NSGigE.hh"
#include "params/NSGigEInt.hh"
#include "sim/debug.hh" #include "sim/debug.hh"
#include "sim/host.hh" #include "sim/host.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
@ -90,7 +89,7 @@ using namespace TheISA;
// NSGigE PCI Device // NSGigE PCI Device
// //
NSGigE::NSGigE(Params *p) NSGigE::NSGigE(Params *p)
: PciDev(p), ioEnable(false), : EtherDevice(p), ioEnable(false),
txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false), txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
@ -118,6 +117,8 @@ NSGigE::NSGigE(Params *p)
{ {
interface = new NSGigEInt(name() + ".int0", this);
regsReset(); regsReset();
memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN); memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
@ -492,6 +493,17 @@ NSGigE::writeConfig(PacketPtr pkt)
return configDelay; return configDelay;
} }
EtherInt*
NSGigE::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;
}
/** /**
* This reads the device registers, which are detailed in the NS83820 * This reads the device registers, which are detailed in the NS83820
* spec sheet * spec sheet
@ -2774,20 +2786,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
} }
} }
NSGigEInt *
NSGigEIntParams::create()
{
NSGigEInt *dev_int = new NSGigEInt(name, device);
EtherInt *p = (EtherInt *)peer;
if (p) {
dev_int->setPeer(p);
p->setPeer(dev_int);
}
return dev_int;
}
NSGigE * NSGigE *
NSGigEParams::create() NSGigEParams::create()
{ {

View file

@ -39,11 +39,11 @@
#include "base/inet.hh" #include "base/inet.hh"
#include "base/statistics.hh" #include "base/statistics.hh"
#include "dev/etherdevice.hh"
#include "dev/etherint.hh" #include "dev/etherint.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "dev/io_device.hh" #include "dev/io_device.hh"
#include "dev/ns_gige_reg.h" #include "dev/ns_gige_reg.h"
#include "dev/pcidev.hh"
#include "dev/pktfifo.hh" #include "dev/pktfifo.hh"
#include "params/NSGigE.hh" #include "params/NSGigE.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
@ -119,7 +119,7 @@ class Packet;
/** /**
* NS DP83820 Ethernet device model * NS DP83820 Ethernet device model
*/ */
class NSGigE : public PciDev class NSGigE : public EtherDevice
{ {
public: public:
/** Transmit State Machine states */ /** Transmit State Machine states */
@ -355,6 +355,8 @@ class NSGigE : public PciDev
NSGigE(Params *params); NSGigE(Params *params);
~NSGigE(); ~NSGigE();
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
virtual Tick writeConfig(PacketPtr pkt); virtual Tick writeConfig(PacketPtr pkt);
virtual Tick read(PacketPtr pkt); virtual Tick read(PacketPtr pkt);
@ -366,8 +368,6 @@ class NSGigE : public PciDev
bool recvPacket(EthPacketPtr packet); bool recvPacket(EthPacketPtr packet);
void transferDone(); void transferDone();
void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
@ -438,7 +438,8 @@ class NSGigEInt : public EtherInt
public: public:
NSGigEInt(const std::string &name, NSGigE *d) NSGigEInt(const std::string &name, NSGigE *d)
: EtherInt(name), dev(d) { dev->setInterface(this); } : EtherInt(name), dev(d)
{ }
virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); } virtual void sendDone() { dev->transferDone(); }

View file

@ -81,7 +81,7 @@ PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp,
} }
PciDev::PciDev(Params *p) PciDev::PciDev(const Params *p)
: DmaDevice(p), plat(p->platform), configData(p->configdata), : DmaDevice(p), plat(p->platform), configData(p->configdata),
pioDelay(p->pio_latency), configDelay(p->config_latency), pioDelay(p->pio_latency), configDelay(p->config_latency),
configPort(NULL) configPort(NULL)

View file

@ -222,7 +222,7 @@ class PciDev : public DmaDevice
* config file object PCIConfigData and registers the device with * config file object PCIConfigData and registers the device with
* a PciConfigAll object. * a PciConfigAll object.
*/ */
PciDev(Params *params); PciDev(const Params *params);
virtual void init(); virtual void init();

View file

@ -73,14 +73,14 @@ const char *TxStateStrings[] =
// //
// Sinic PCI Device // Sinic PCI Device
// //
Base::Base(Params *p) Base::Base(const Params *p)
: PciDev(p), rxEnable(false), txEnable(false), clock(p->clock), : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false), intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
cpuPendingIntr(false), intrEvent(0), interface(NULL) cpuPendingIntr(false), intrEvent(0), interface(NULL)
{ {
} }
Device::Device(Params *p) Device::Device(const Params *p)
: Base(p), rxUnique(0), txUnique(0), : Base(p), rxUnique(0), txUnique(0),
virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count), virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
@ -89,6 +89,7 @@ Device::Device(Params *p)
dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor), dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor) dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
{ {
interface = new Interface(name() + ".int0", this);
reset(); reset();
} }
@ -266,6 +267,19 @@ Device::regStats()
rxPacketRate = rxPackets / 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;
}
void void
Device::prepareIO(int cpu, int index) Device::prepareIO(int cpu, int index)
{ {
@ -1595,21 +1609,6 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
/* namespace Sinic */ } /* namespace Sinic */ }
Sinic::Interface *
SinicIntParams::create()
{
using namespace Sinic;
Interface *dev_int = new Interface(name, device);
if (peer) {
dev_int->setPeer(peer);
peer->setPeer(dev_int);
}
return dev_int;
}
Sinic::Device * Sinic::Device *
SinicParams::create() SinicParams::create()
{ {

View file

@ -40,7 +40,6 @@
#include "dev/pktfifo.hh" #include "dev/pktfifo.hh"
#include "dev/sinicreg.hh" #include "dev/sinicreg.hh"
#include "params/Sinic.hh" #include "params/Sinic.hh"
#include "params/SinicInt.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
namespace Sinic { namespace Sinic {
@ -84,7 +83,7 @@ class Base : public PciDev
public: public:
typedef SinicParams Params; typedef SinicParams Params;
const Params *params() const { return (const Params *)_params; } const Params *params() const { return (const Params *)_params; }
Base(Params *p); Base(const Params *p);
}; };
class Device : public Base class Device : public Base
@ -231,7 +230,7 @@ class Device : public Base
public: public:
bool recvPacket(EthPacketPtr packet); bool recvPacket(EthPacketPtr packet);
void transferDone(); void transferDone();
void setInterface(Interface *i) { assert(!interface); interface = i; } virtual EtherInt *getEthPort(const std::string &if_name, int idx);
/** /**
* DMA parameters * DMA parameters
@ -312,7 +311,7 @@ class Device : public Base
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
public: public:
Device(Params *p); Device(const Params *p);
~Device(); ~Device();
}; };
@ -326,7 +325,8 @@ class Interface : public EtherInt
public: public:
Interface(const std::string &name, Device *d) Interface(const std::string &name, Device *d)
: EtherInt(name), dev(d) { dev->setInterface(this); } : EtherInt(name), dev(d)
{ }
virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); } virtual void sendDone() { dev->transferDone(); }

View file

@ -34,6 +34,9 @@
#include "base/inifile.hh" #include "base/inifile.hh"
#include "base/output.hh" #include "base/output.hh"
#include "dev/etherdevice.hh"
#include "dev/etherobject.hh"
#include "dev/etherint.hh"
#include "mem/mem_object.hh" #include "mem/mem_object.hh"
#include "mem/port.hh" #include "mem/port.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
@ -58,6 +61,23 @@ lookupPort(SimObject *so, const std::string &name, int i)
return p; return p;
} }
EtherInt *
lookupEthPort(SimObject *so, const std::string &name, int i)
{
EtherObject *eo = dynamic_cast<EtherObject *>(so);
EtherDevice *ed = dynamic_cast<EtherDevice *>(so);
if (eo == NULL && ed == NULL) {
warn("error casting SimObject %s", so->name());
return NULL;
}
EtherInt *p = NULL;
if (eo)
p = eo->getEthPort(name, i);
else
p = ed->getEthPort(name, i);
return p;
}
/** /**
* Connect the described MemObject ports. Called from Python via SWIG. * Connect the described MemObject ports. Called from Python via SWIG.
@ -67,6 +87,31 @@ int
connectPorts(SimObject *o1, const std::string &name1, int i1, connectPorts(SimObject *o1, const std::string &name1, int i1,
SimObject *o2, const std::string &name2, int i2) SimObject *o2, const std::string &name2, int i2)
{ {
EtherObject *eo1, *eo2;
EtherDevice *ed1, *ed2;
MemObject *mo1, *mo2;
eo1 = dynamic_cast<EtherObject*>(o1);
ed1 = dynamic_cast<EtherDevice*>(o1);
mo1 = dynamic_cast<MemObject*>(o1);
eo2 = dynamic_cast<EtherObject*>(o2);
ed2 = dynamic_cast<EtherDevice*>(o2);
mo2 = dynamic_cast<MemObject*>(o2);
if ((eo1 || ed1) && (eo2 || ed2)) {
EtherInt *p1 = lookupEthPort(o1, name1, i1);
EtherInt *p2 = lookupEthPort(o2, name2, i2);
if (p1 != NULL && p2 != NULL) {
p1->setPeer(p2);
p2->setPeer(p1);
return 1;
}
}
Port *p1 = lookupPort(o1, name1, i1); Port *p1 = lookupPort(o1, name1, i1);
Port *p2 = lookupPort(o2, name2, i2); Port *p2 = lookupPort(o2, name2, i2);