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:
parent
5c6835ae3f
commit
8654cfa427
4 changed files with 173 additions and 67 deletions
104
dev/io_device.cc
104
dev/io_device.cc
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
127
dev/io_device.hh
127
dev/io_device.hh
|
@ -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__
|
||||
|
|
|
@ -54,7 +54,8 @@ enum Command
|
|||
enum PacketResult
|
||||
{
|
||||
Success,
|
||||
BadAddress
|
||||
BadAddress,
|
||||
Unknown
|
||||
};
|
||||
|
||||
class SenderState{};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue