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 "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
127
dev/io_device.hh
127
dev/io_device.hh
|
@ -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__
|
||||||
|
|
|
@ -54,7 +54,8 @@ enum Command
|
||||||
enum PacketResult
|
enum PacketResult
|
||||||
{
|
{
|
||||||
Success,
|
Success,
|
||||||
BadAddress
|
BadAddress,
|
||||||
|
Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
class SenderState{};
|
class SenderState{};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue