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

View file

@ -32,30 +32,56 @@
#include "base/chunk_generator.hh"
#include "mem/port.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
class Bus;
class Platform;
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
{
protected:
/** The device that this port serves. */
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 Tick recvAtomic(Packet &pkt)
{ return device->recvAtomic(pkt) };
virtual Tick recvAtomic(Packet &pkt);
virtual void recvFunctional(Packet &pkt)
{ device->recvAtomic(pkt) };
virtual void recvFunctional(Packet &pkt) ;
virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
{ device->addressRanges(range_list, owner); }
virtual void recvStatusChange(Status status)
{ peerStatus = status; }
void sendTiming(Packet &pkt, Tick time)
{ new SendEvent(this, pkt, time); }
virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner);
/**
* 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
{
PioPort *port;
@ -71,13 +97,19 @@ class PioPort : public Port
{ return "Future scheduled sendTiming event"; }
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:
PioPort(PioDevice *dev)
: device(dev)
{ }
PioPort(PioDevice *dev, Platform *p);
friend class PioPort::SendEvent;
};
class DmaPort : public Port
@ -85,10 +117,10 @@ class DmaPort : public Port
protected:
PioDevice *device;
std::list<Packet*> transmitList;
Event *completionEvent;
virtual bool recvTiming(Packet &pkt)
{ completionEvent->schedule(curTick+1); completionEvent = NULL; }
virtual bool recvTiming(Packet &pkt);
virtual Tick recvAtomic(Packet &pkt)
{ panic("dma port shouldn't be used for pio access."); }
virtual void recvFunctional(Packet &pkt)
@ -97,23 +129,14 @@ class DmaPort : public Port
virtual void recvStatusChange(Status status)
{ ; }
virtual Packet *recvRetry()
{ return transmitList.pop_front(); }
virtual Packet *recvRetry() ;
virtual void getDeviceAddressRanges(AddrRangeList &range_list, bool &owner)
{ 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
{
PioPort *port;
DmaPort *port;
Packet packet;
SendEvent(PioPort *p, Packet &pkt, Tick t)
@ -125,33 +148,55 @@ class DmaPort : public Port
virtual const char *description()
{ return "Future scheduled sendTiming event"; }
friend class PioPort;
}
public:
DmaPort(DmaDevice *dev)
: device(dev)
{ }
friend class DmaPort;
};
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
{
protected:
/** The platform we are in. This is used to decide what type of memory
* transaction we should perform. */
Platform *platform;
/** The pioPort that handles the requests for us and provides us requests
* that it sees. */
PioPort *pioPort;
virtual void addressRanges(AddrRangeList &range_list, bool &owner) = 0;
virtual read(Packet &pkt) = 0;
virtual write(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. */
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:
PioDevice(const std::string &name, Platform *p);
@ -165,6 +210,8 @@ class PioDevice : public SimObject
else
return NULL;
}
friend class PioPort;
};
class DmaDevice : public PioDevice
@ -180,14 +227,14 @@ class DmaDevice : public PioDevice
{
if (if_name == "pio")
return pioPort;
else if (if_name = "dma")
else if (if_name == "dma")
return dmaPort;
else
return NULL;
}
friend class DmaPort;
};
#endif // __DEV_IO_DEVICE_HH__

View file

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

View file

@ -73,7 +73,11 @@ class Request
int size;
/** 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. */
Addr copyDest;