Make PioPort/DmaPort,DmaDevice/PioDevice compile.

Add another type to the PacketResult enum of Unknown
Seperate time into requsetTime and responseTime.

dev/io_device.cc:
dev/io_device.hh:
    Make PioPort/DmaPort,DmaDevice/PioDevice compile.
mem/packet.hh:
    Add another type to the PacketResult enum of Unknown (e.g. no state set yet)
mem/request.hh:
    Seperate time into requsetTime and responseTime.

--HG--
extra : convert_revision : c6394cb838013296caea6492275252b8cae2882f
This commit is contained in:
Ali Saidi 2006-03-21 15:45:31 -05:00
parent 5c6835ae3f
commit 8654cfa427
4 changed files with 173 additions and 67 deletions

View file

@ -29,10 +29,44 @@
#include "dev/io_device.hh" #include "dev/io_device.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
PioPort::PioPort(PioDevice *dev)
: device(dev)
{ }
Tick
PioPort::recvAtomic(Packet &pkt)
{
return device->recvAtomic(pkt);
}
void
PioPort::recvFunctional(Packet &pkt)
{
device->recvAtomic(pkt);
}
void
PioPort::getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
{
device->addressRanges(range_list, owner);
}
Packet *
PioPort::recvRetry()
{
Packet* pkt = transmitList.front();
transmitList.pop_front();
return pkt;
}
void void
PioPort::SendEvent::process() PioPort::SendEvent::process()
{ {
if (port->sendTiming(packet) == Success) if (port->Port::sendTiming(packet) == Success)
return; return;
port->transmitList.push_back(&packet); port->transmitList.push_back(&packet);
@ -46,37 +80,57 @@ PioDevice::PioDevice(const std::string &name, Platform *p)
bool bool
PioDevice::recvTiming(Packet &pkt) PioPort::recvTiming(Packet &pkt)
{ {
device->recvAtomic(pkt); device->recvAtomic(pkt);
sendTiming(pkt, pkt.responseTime-pkt.requestTime); sendTiming(pkt, pkt.req->responseTime-pkt.req->requestTime);
return Success; return Success;
} }
PioDevice::~PioDevice() PioDevice::~PioDevice()
{ {
if (pioPort) if (pioPort)
delete pioInterface; delete pioPort;
} }
void
DmaPort::sendDma(Packet &pkt) DmaPort::DmaPort(DmaDevice *dev)
: device(dev)
{ }
bool
DmaPort::recvTiming(Packet &pkt)
{ {
device->platform->system->memoryMode() completionEvent->schedule(curTick+1);
{ completionEvent = NULL;
case MemAtomic: return Success;
}
} }
DmaDevice::DmaDevice(const std::string &name, Platform *p) DmaDevice::DmaDevice(const std::string &name, Platform *p)
: PioDevice(name, p) : PioDevice(name, p)
{ {
dmaPort = new dmaPort(this); dmaPort = new DmaPort(this);
} }
void void
DmaPort::dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size, DmaPort::SendEvent::process()
Event *event, uint8_t *data = NULL) {
if (port->Port::sendTiming(packet) == Success)
return;
port->transmitList.push_back(&packet);
}
Packet *
DmaPort::recvRetry()
{
Packet* pkt = transmitList.front();
transmitList.pop_front();
return pkt;
}
void
DmaPort::dmaAction(Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data)
{ {
assert(event); assert(event);
@ -92,9 +146,9 @@ DmaPort::dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
basePkt.dest = 0; basePkt.dest = 0;
basePkt.cmd = cmd; basePkt.cmd = cmd;
basePkt.result = Unknown; basePkt.result = Unknown;
basePkt.request = NULL; basePkt.req = NULL;
baseReq.nicReq = true; baseReq.nicReq = true;
baseReq.time = curTick; baseReq.requestTime = curTick;
completionEvent = event; completionEvent = event;
@ -109,7 +163,7 @@ DmaPort::dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
pkt->req->size = pkt->size; pkt->req->size = pkt->size;
// Increment the data pointer on a write // Increment the data pointer on a write
pkt->data = data ? data + prevSize : NULL ; pkt->data = data ? data + prevSize : NULL ;
prevSize = pkt->size; prevSize += pkt->size;
sendDma(*pkt); sendDma(*pkt);
} }
@ -122,29 +176,29 @@ DmaPort::sendDma(Packet &pkt)
// some kind of selction between access methods // some kind of selction between access methods
// more work is going to have to be done to make // more work is going to have to be done to make
// switching actually work // switching actually work
MemState state = device->platform->system->memState; /* MemState state = device->platform->system->memState;
if (state == Timing) { if (state == Timing) {
if (sendTiming(pkt) == Failure) if (sendTiming(pkt) == Failure)
transmitList.push_back(&packet); transmitList.push_back(&packet);
} else if (state == Atomic) { } else if (state == Atomic) {*/
sendAtomic(pkt); sendAtomic(pkt);
completionEvent->schedule(pkt.responseTime - pkt.requestTime); completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
completionEvent == NULL; completionEvent = NULL;
} else if (state == Functional) { /* } else if (state == Functional) {
sendFunctional(pkt); sendFunctional(pkt);
// Is this correct??? // Is this correct???
completionEvent->schedule(pkt.responseTime - pkt.requestTime); completionEvent->schedule(pkt.req->responseTime - pkt.req->requestTime);
completionEvent == NULL; completionEvent == NULL;
} else } else
panic("Unknown memory command state."); panic("Unknown memory command state.");
*/
} }
DmaDevice::~DmaDevice() DmaDevice::~DmaDevice()
{ {
if (dmaInterface) if (dmaPort)
delete dmaInterface; delete dmaPort;
} }

View file

@ -32,30 +32,56 @@
#include "base/chunk_generator.hh" #include "base/chunk_generator.hh"
#include "mem/port.hh" #include "mem/port.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "sim/sim_object.hh"
class Bus;
class Platform; class Platform;
class PioDevice; class PioDevice;
class DmaDevice;
/**
* The PioPort class is a programmed i/o port that all devices that are
* sensitive to an address range use. The port takes all the memory
* access types and roles them into one read() and write() call that the device
* must respond to. The device must also provide the addressRanges() function
* with which it returns the address ranges it is interested in. An extra
* sendTiming() function is implemented which takes an delay. In this way the
* device can immediatly call sendTiming(pkt, time) after processing a request
* and the request will be handled by the port even if the port bus the device
* connects to is blocked.
*/
class PioPort : public Port class PioPort : public Port
{ {
protected: protected:
/** The device that this port serves. */
PioDevice *device; PioDevice *device;
/** The platform that device/port are in. This is used to select which mode
* we are currently operating in. */
Platfrom *platform;
/** A list of outgoing timing response packets that haven't been serviced
* yet. */
std::list<Packet*> transmitList;
/** The current status of the peer(bus) that we are connected to. */
Status peerStatus;
virtual bool recvTiming(Packet &pkt); virtual bool recvTiming(Packet &pkt);
virtual Tick recvAtomic(Packet &pkt) virtual Tick recvAtomic(Packet &pkt);
{ return device->recvAtomic(pkt) };
virtual void recvFunctional(Packet &pkt) virtual void recvFunctional(Packet &pkt) ;
{ device->recvAtomic(pkt) };
virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner) virtual void recvStatusChange(Status status)
{ device->addressRanges(range_list, owner); } { peerStatus = status; }
void sendTiming(Packet &pkt, Tick time) virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner);
{ new SendEvent(this, pkt, time); }
/**
* This class is used to implemented sendTiming() with a delay. When a delay
* is requested a new event is created. When the event time expires it
* attempts to send the packet. If it cannot, the packet is pushed onto the
* transmit list to be sent when recvRetry() is called. */
class SendEvent : public Event class SendEvent : public Event
{ {
PioPort *port; PioPort *port;
@ -71,13 +97,19 @@ class PioPort : public Port
{ return "Future scheduled sendTiming event"; } { return "Future scheduled sendTiming event"; }
friend class PioPort; friend class PioPort;
} };
/** Schedule a sendTiming() event to be called in the future. */
void sendTiming(Packet &pkt, Tick time)
{ new PioPort::SendEvent(this, pkt, time); }
/** This function pops the last element off the transmit list and sends it.*/
virtual Packet *recvRetry();
public: public:
PioPort(PioDevice *dev) PioPort(PioDevice *dev, Platform *p);
: device(dev)
{ }
friend class PioPort::SendEvent;
}; };
class DmaPort : public Port class DmaPort : public Port
@ -85,10 +117,10 @@ class DmaPort : public Port
protected: protected:
PioDevice *device; PioDevice *device;
std::list<Packet*> transmitList; std::list<Packet*> transmitList;
Event *completionEvent;
virtual bool recvTiming(Packet &pkt) virtual bool recvTiming(Packet &pkt);
{ completionEvent->schedule(curTick+1); completionEvent = NULL; }
virtual Tick recvAtomic(Packet &pkt) virtual Tick recvAtomic(Packet &pkt)
{ panic("dma port shouldn't be used for pio access."); } { panic("dma port shouldn't be used for pio access."); }
virtual void recvFunctional(Packet &pkt) virtual void recvFunctional(Packet &pkt)
@ -97,23 +129,14 @@ class DmaPort : public Port
virtual void recvStatusChange(Status status) virtual void recvStatusChange(Status status)
{ ; } { ; }
virtual Packet *recvRetry() virtual Packet *recvRetry() ;
{ return transmitList.pop_front(); }
virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner) virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
{ range_list.clear(); owner = true; } { range_list.clear(); owner = true; }
void dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data = NULL);
void sendDma(Packet &pkt);
virtual Packet *recvRetry()
{ return transmitList.pop_front(); }
class SendEvent : public Event class SendEvent : public Event
{ {
PioPort *port; DmaPort *port;
Packet packet; Packet packet;
SendEvent(PioPort *p, Packet &pkt, Tick t) SendEvent(PioPort *p, Packet &pkt, Tick t)
@ -125,33 +148,55 @@ class DmaPort : public Port
virtual const char *description() virtual const char *description()
{ return "Future scheduled sendTiming event"; } { return "Future scheduled sendTiming event"; }
friend class PioPort; friend class DmaPort;
} };
public:
DmaPort(DmaDevice *dev)
: device(dev)
{ }
void dmaAction(Command cmd, DmaPort port, Addr addr, int size,
Event *event, uint8_t *data = NULL);
void sendDma(Packet &pkt);
public:
DmaPort(DmaDevice *dev);
friend class DmaPort::SendEvent;
}; };
/**
* This device is the base class which all devices senstive to an address range
* inherit from. There are three pure virtual functions which all devices must
* implement addressRanges(), read(), and write(). The magic do choose which
* mode we are in, etc is handled by the PioPort so the device doesn't have to
* bother.
*/
class PioDevice : public SimObject class PioDevice : public SimObject
{ {
protected: protected:
/** The platform we are in. This is used to decide what type of memory
* transaction we should perform. */
Platform *platform; Platform *platform;
/** The pioPort that handles the requests for us and provides us requests
* that it sees. */
PioPort *pioPort; PioPort *pioPort;
virtual void addressRanges(AddrRangeList &range_list, bool &owner) = 0; virtual void addressRanges(AddrRangeList &range_list, bool &owner) = 0;
virtual read(Packet &pkt) = 0; /** As far as the devices are concerned they only accept atomic transactions
* which are converted to either a write or a read. */
virtual write(Packet &pkt) = 0;
Tick recvAtomic(Packet &pkt) Tick recvAtomic(Packet &pkt)
{ return pkt->cmd == Read ? this->read(pkt) : this->write(pkt); } { return pkt.cmd == Read ? this->read(pkt) : this->write(pkt); }
/** Pure virtual function that the device must implement. Called when a read
* command is recieved by the port. */
virtual bool read(Packet &pkt) = 0;
/** Pure virtual function that the device must implement. Called when a
* write command is recieved by the port. */
virtual bool write(Packet &pkt) = 0;
public: public:
PioDevice(const std::string &name, Platform *p); PioDevice(const std::string &name, Platform *p);
@ -165,6 +210,8 @@ class PioDevice : public SimObject
else else
return NULL; return NULL;
} }
friend class PioPort;
}; };
class DmaDevice : public PioDevice class DmaDevice : public PioDevice
@ -180,14 +227,14 @@ class DmaDevice : public PioDevice
{ {
if (if_name == "pio") if (if_name == "pio")
return pioPort; return pioPort;
else if (if_name = "dma") else if (if_name == "dma")
return dmaPort; return dmaPort;
else else
return NULL; return NULL;
} }
friend class DmaPort;
}; };
#endif // __DEV_IO_DEVICE_HH__ #endif // __DEV_IO_DEVICE_HH__

View file

@ -54,7 +54,8 @@ enum Command
enum PacketResult enum PacketResult
{ {
Success, Success,
BadAddress BadAddress,
Unknown
}; };
class SenderState{}; class SenderState{};

View file

@ -73,7 +73,11 @@ class Request
int size; int size;
/** The time this request was started. Used to calculate latencies. */ /** The time this request was started. Used to calculate latencies. */
Tick time; Tick requestTime;
/** The time this request was responded to in the memory hierachy. Used by
* deviced to inform ports how long a request should be delayed. */
Tick responseTime;
/** Destination address if this is a block copy. */ /** Destination address if this is a block copy. */
Addr copyDest; Addr copyDest;