memory mode information now contained in system object
States are now running, draining, or drained. memory state information moved into system object
system parameter is not fs only for cpus
Implement drain() support in devices
Update for drain() call that returns number of times drain_event->process() will be called
Break O3 CPU! No sense in putting in a hack change that kevin is going to remove in a few minutes i imagine
src/cpu/simple/atomic.cc:
src/cpu/simple/atomic.hh:
Since se mode has a system, allow access to it
Verify that the atomic cpu is connected to an atomic system on resume
src/cpu/simple/base.cc:
Since se mode has a system, allow access to it
src/cpu/simple/timing.cc:
src/cpu/simple/timing.hh:
Update for new drain() call that returns number of times drain_event->process() will be called and memory state being moved into the system
Since se mode has a system, allow access to it
Verify that the timing cpu is connected to an timing system on resume
src/dev/ide_disk.cc:
src/dev/io_device.cc:
src/dev/io_device.hh:
src/dev/ns_gige.cc:
src/dev/ns_gige.hh:
src/dev/pcidev.cc:
src/dev/pcidev.hh:
src/dev/sinic.cc:
src/dev/sinic.hh:
Implement drain() support in devices
src/python/m5/config.py:
Allow drain to return number of times drain_event->process() will be called. Normally 0 or 1 but things like O3 cpu or devices with multiple ports may want to call it many times
src/python/m5/objects/BaseCPU.py:
move system parameter out of fs to everyone
src/sim/sim_object.cc:
src/sim/sim_object.hh:
States are now running, draining, or drained. memory state information moved into system object
src/sim/system.cc:
src/sim/system.hh:
memory mode information now contained in system object
--HG--
extra : convert_revision : 1389c77e66ee6d9710bf77b4306fb47e107b21cf
This commit is contained in:
@@ -318,7 +318,7 @@ IdeDisk::doDmaTransfer()
|
||||
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
|
||||
dmaState, devState);
|
||||
|
||||
if (ctrl->dmaPending()) {
|
||||
if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
|
||||
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
|
||||
return;
|
||||
} else
|
||||
@@ -398,8 +398,7 @@ IdeDisk::doDmaRead()
|
||||
curPrd.getByteCount(), TheISA::PageBytes);
|
||||
|
||||
}
|
||||
if (ctrl->dmaPending()) {
|
||||
panic("shouldn't be reentant??");
|
||||
if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
|
||||
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
|
||||
return;
|
||||
} else if (!dmaReadCG->done()) {
|
||||
@@ -474,8 +473,7 @@ IdeDisk::doDmaWrite()
|
||||
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
|
||||
curPrd.getByteCount(), TheISA::PageBytes);
|
||||
}
|
||||
if (ctrl->dmaPending()) {
|
||||
panic("shouldn't be reentant??");
|
||||
if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
|
||||
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
|
||||
return;
|
||||
} else if (!dmaWriteCG->done()) {
|
||||
|
||||
@@ -32,10 +32,12 @@
|
||||
#include "base/trace.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
|
||||
PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
|
||||
: Port(dev->name() + pname), device(dev), platform(p)
|
||||
PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
|
||||
: Port(dev->name() + pname), device(dev), sys(s),
|
||||
outTiming(0), drainEvent(NULL)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -68,13 +70,23 @@ PioPort::recvRetry()
|
||||
if (result)
|
||||
transmitList.pop_front();
|
||||
}
|
||||
if (transmitList.size() == 0 && drainEvent) {
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PioPort::SendEvent::process()
|
||||
{
|
||||
port->outTiming--;
|
||||
assert(port->outTiming >= 0);
|
||||
if (port->Port::sendTiming(packet))
|
||||
return;
|
||||
if (port->transmitList.size() == 0 && port->drainEvent) {
|
||||
port->drainEvent->process();
|
||||
port->drainEvent = NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
port->transmitList.push_back(packet);
|
||||
}
|
||||
@@ -105,6 +117,15 @@ PioPort::recvTiming(Packet *pkt)
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PioPort::drain(Event *de)
|
||||
{
|
||||
if (outTiming == 0 && transmitList.size() == 0)
|
||||
return 0;
|
||||
drainEvent = de;
|
||||
return 1;
|
||||
}
|
||||
|
||||
PioDevice::~PioDevice()
|
||||
{
|
||||
if (pioPort)
|
||||
@@ -119,6 +140,19 @@ PioDevice::init()
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
PioDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
BasicPioDevice::addressRanges(AddrRangeList &range_list)
|
||||
{
|
||||
@@ -128,8 +162,9 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
|
||||
}
|
||||
|
||||
|
||||
DmaPort::DmaPort(DmaDevice *dev, Platform *p)
|
||||
: Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0)
|
||||
DmaPort::DmaPort(DmaDevice *dev, System *s)
|
||||
: Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0),
|
||||
actionInProgress(0), drainEvent(NULL)
|
||||
{ }
|
||||
|
||||
bool
|
||||
@@ -159,6 +194,11 @@ DmaPort::recvTiming(Packet *pkt)
|
||||
}
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
if (pendingCount == 0 && drainEvent) {
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
} else {
|
||||
panic("Got packet without sender state... huh?\n");
|
||||
}
|
||||
@@ -170,6 +210,29 @@ DmaDevice::DmaDevice(Params *p)
|
||||
: PioDevice(p), dmaPort(NULL)
|
||||
{ }
|
||||
|
||||
|
||||
unsigned int
|
||||
DmaDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
DmaPort::drain(Event *de)
|
||||
{
|
||||
if (pendingCount == 0)
|
||||
return 0;
|
||||
drainEvent = de;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DmaPort::recvRetry()
|
||||
{
|
||||
@@ -195,6 +258,8 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||
{
|
||||
assert(event);
|
||||
|
||||
assert(device->getState() == SimObject::Running);
|
||||
|
||||
DmaReqState *reqState = new DmaReqState(event, this, size);
|
||||
|
||||
for (ChunkGenerator gen(addr, size, peerBlockSize());
|
||||
@@ -212,51 +277,53 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||
pendingCount++;
|
||||
sendDma(pkt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DmaPort::sendDma(Packet *pkt, bool front)
|
||||
{
|
||||
// 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;
|
||||
// some kind of selction between access methods
|
||||
// more work is going to have to be done to make
|
||||
// switching actually work
|
||||
System::MemoryMode state = sys->getMemoryMode();
|
||||
if (state == System::Timing) {
|
||||
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
|
||||
pkt, pkt->getAddr());
|
||||
if (transmitList.size() || !sendTiming(pkt)) {
|
||||
if (front)
|
||||
transmitList.push_front(pkt);
|
||||
else
|
||||
transmitList.push_back(pkt);
|
||||
DPRINTF(DMA, "-- Failed: queued\n");
|
||||
} else {
|
||||
DPRINTF(DMA, "-- Done\n");
|
||||
}
|
||||
} else if (state == System::Atomic) {
|
||||
sendAtomic(pkt);
|
||||
assert(pkt->senderState);
|
||||
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||
assert(state);
|
||||
|
||||
if (state == Timing) { */
|
||||
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
|
||||
pkt, pkt->getAddr());
|
||||
if (transmitList.size() || !sendTiming(pkt)) {
|
||||
if (front)
|
||||
transmitList.push_front(pkt);
|
||||
else
|
||||
transmitList.push_back(pkt);
|
||||
DPRINTF(DMA, "-- Failed: queued\n");
|
||||
} else {
|
||||
DPRINTF(DMA, "-- Done\n");
|
||||
}
|
||||
/* } else if (state == Atomic) {
|
||||
sendAtomic(pkt);
|
||||
if (pkt->senderState) {
|
||||
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||
assert(state);
|
||||
state->completionEvent->schedule(curTick + (pkt->time -
|
||||
pkt->req->getTime()) +1);
|
||||
delete state;
|
||||
}
|
||||
pendingCount--;
|
||||
assert(pendingCount >= 0);
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
state->numBytes += pkt->req->getSize();
|
||||
if (state->totBytes == state->numBytes) {
|
||||
state->completionEvent->schedule(curTick +
|
||||
(pkt->time - pkt->req->getTime()) +1);
|
||||
delete state;
|
||||
delete pkt->req;
|
||||
}
|
||||
pendingCount--;
|
||||
assert(pendingCount >= 0);
|
||||
delete pkt;
|
||||
|
||||
if (pendingCount == 0 && drainEvent) {
|
||||
drainEvent->process();
|
||||
drainEvent = NULL;
|
||||
}
|
||||
|
||||
} else if (state == Functional) {
|
||||
sendFunctional(pkt);
|
||||
// Is this correct???
|
||||
completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
|
||||
completionEvent == NULL;
|
||||
} else
|
||||
panic("Unknown memory command state.");
|
||||
*/
|
||||
}
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
|
||||
@@ -60,9 +60,9 @@ class PioPort : public Port
|
||||
/** The device that this port serves. */
|
||||
PioDevice *device;
|
||||
|
||||
/** The platform that device/port are in. This is used to select which mode
|
||||
/** The system that device/port are in. This is used to select which mode
|
||||
* we are currently operating in. */
|
||||
Platform *platform;
|
||||
System *sys;
|
||||
|
||||
/** A list of outgoing timing response packets that haven't been serviced
|
||||
* yet. */
|
||||
@@ -106,16 +106,27 @@ class PioPort : public Port
|
||||
friend class PioPort;
|
||||
};
|
||||
|
||||
/** Number of timing requests that are emulating the device timing before
|
||||
* attempting to end up on the bus.
|
||||
*/
|
||||
int outTiming;
|
||||
|
||||
/** If we need to drain, keep the drain event around until we're done
|
||||
* here.*/
|
||||
Event *drainEvent;
|
||||
|
||||
/** Schedule a sendTiming() event to be called in the future. */
|
||||
void sendTiming(Packet *pkt, Tick time)
|
||||
{ new PioPort::SendEvent(this, pkt, time); }
|
||||
{ outTiming++; new PioPort::SendEvent(this, pkt, time); }
|
||||
|
||||
/** This function is notification that the device should attempt to send a
|
||||
* packet again. */
|
||||
virtual void recvRetry();
|
||||
|
||||
public:
|
||||
PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
|
||||
PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
|
||||
|
||||
unsigned int drain(Event *de);
|
||||
|
||||
friend class PioPort::SendEvent;
|
||||
};
|
||||
@@ -147,13 +158,20 @@ class DmaPort : public Port
|
||||
DmaDevice *device;
|
||||
std::list<Packet*> transmitList;
|
||||
|
||||
/** The platform that device/port are in. This is used to select which mode
|
||||
/** The system that device/port are in. This is used to select which mode
|
||||
* we are currently operating in. */
|
||||
Platform *platform;
|
||||
System *sys;
|
||||
|
||||
/** Number of outstanding packets the dma port has. */
|
||||
int pendingCount;
|
||||
|
||||
/** If a dmaAction is in progress. */
|
||||
int actionInProgress;
|
||||
|
||||
/** If we need to drain, keep the drain event around until we're done
|
||||
* here.*/
|
||||
Event *drainEvent;
|
||||
|
||||
virtual bool recvTiming(Packet *pkt);
|
||||
virtual Tick recvAtomic(Packet *pkt)
|
||||
{ panic("dma port shouldn't be used for pio access."); }
|
||||
@@ -171,13 +189,14 @@ class DmaPort : public Port
|
||||
void sendDma(Packet *pkt, bool front = false);
|
||||
|
||||
public:
|
||||
DmaPort(DmaDevice *dev, Platform *p);
|
||||
DmaPort(DmaDevice *dev, System *s);
|
||||
|
||||
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||
uint8_t *data = NULL);
|
||||
|
||||
bool dmaPending() { return pendingCount > 0; }
|
||||
|
||||
unsigned int drain(Event *de);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -196,6 +215,8 @@ class PioDevice : public MemObject
|
||||
* transaction we should perform. */
|
||||
Platform *platform;
|
||||
|
||||
System *sys;
|
||||
|
||||
/** The pioPort that handles the requests for us and provides us requests
|
||||
* that it sees. */
|
||||
PioPort *pioPort;
|
||||
@@ -240,20 +261,22 @@ class PioDevice : public MemObject
|
||||
const Params *params() const { return _params; }
|
||||
|
||||
PioDevice(Params *p)
|
||||
: MemObject(p->name), platform(p->platform), pioPort(NULL),
|
||||
_params(p)
|
||||
: MemObject(p->name), platform(p->platform), sys(p->system),
|
||||
pioPort(NULL), _params(p)
|
||||
{}
|
||||
|
||||
virtual ~PioDevice();
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "pio") {
|
||||
if (pioPort != NULL)
|
||||
panic("pio port already connected to.");
|
||||
pioPort = new PioPort(this, params()->platform);
|
||||
pioPort = new PioPort(this, sys);
|
||||
return pioPort;
|
||||
} else
|
||||
return NULL;
|
||||
@@ -310,17 +333,19 @@ class DmaDevice : public PioDevice
|
||||
|
||||
bool dmaPending() { return dmaPort->dmaPending(); }
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "pio") {
|
||||
if (pioPort != NULL)
|
||||
panic("pio port already connected to.");
|
||||
pioPort = new PioPort(this, params()->platform);
|
||||
pioPort = new PioPort(this, sys);
|
||||
return pioPort;
|
||||
} else if (if_name == "dma") {
|
||||
if (dmaPort != NULL)
|
||||
panic("dma port already connected to.");
|
||||
dmaPort = new DmaPort(this, params()->platform);
|
||||
dmaPort = new DmaPort(this, sys);
|
||||
return dmaPort;
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
@@ -1377,7 +1377,7 @@ NSGigE::doRxDmaRead()
|
||||
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
|
||||
rxDmaState = dmaReading;
|
||||
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
rxDmaState = dmaReadWaiting;
|
||||
else
|
||||
dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
|
||||
@@ -1408,7 +1408,7 @@ NSGigE::doRxDmaWrite()
|
||||
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
|
||||
rxDmaState = dmaWriting;
|
||||
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
rxDmaState = dmaWriteWaiting;
|
||||
else
|
||||
dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
|
||||
@@ -1826,7 +1826,7 @@ NSGigE::doTxDmaRead()
|
||||
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
|
||||
txDmaState = dmaReading;
|
||||
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
txDmaState = dmaReadWaiting;
|
||||
else
|
||||
dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
|
||||
@@ -1857,7 +1857,7 @@ NSGigE::doTxDmaWrite()
|
||||
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
|
||||
txDmaState = dmaWriting;
|
||||
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
txDmaState = dmaWriteWaiting;
|
||||
else
|
||||
dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
|
||||
@@ -2406,6 +2406,20 @@ NSGigE::recvPacket(EthPacketPtr packet)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NSGigE::resume()
|
||||
{
|
||||
SimObject::resume();
|
||||
|
||||
// During drain we could have left the state machines in a waiting state and
|
||||
// they wouldn't get out until some other event occured to kick them.
|
||||
// This way they'll get out immediately
|
||||
txKick();
|
||||
rxKick();
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
//
|
||||
|
||||
@@ -391,6 +391,8 @@ class NSGigE : public PciDev
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
virtual void resume();
|
||||
|
||||
public:
|
||||
void regStats();
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ using namespace std;
|
||||
|
||||
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
|
||||
int funcid, Platform *p)
|
||||
: PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid),
|
||||
functionId(funcid)
|
||||
: PioPort(dev,p->system,"-pciconf"), device(dev), platform(p),
|
||||
busId(busid), deviceId(devid), functionId(funcid)
|
||||
{
|
||||
configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
|
||||
}
|
||||
@@ -132,6 +132,18 @@ PciDev::init()
|
||||
PioDevice::init();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PciDev::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
changeState(Drained);
|
||||
return count;
|
||||
}
|
||||
|
||||
Tick
|
||||
PciDev::readConfig(Packet *pkt)
|
||||
{
|
||||
|
||||
@@ -95,6 +95,8 @@ class PciDev : public DmaDevice
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
|
||||
|
||||
Platform *platform;
|
||||
|
||||
int busId;
|
||||
int deviceId;
|
||||
int functionId;
|
||||
@@ -249,6 +251,9 @@ class PciDev : public DmaDevice
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "config") {
|
||||
|
||||
@@ -921,7 +921,7 @@ Device::rxKick()
|
||||
break;
|
||||
|
||||
case rxBeginCopy:
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
goto exit;
|
||||
|
||||
rxDmaAddr = params()->platform->pciToDma(
|
||||
@@ -1109,7 +1109,7 @@ Device::txKick()
|
||||
break;
|
||||
|
||||
case txBeginCopy:
|
||||
if (dmaPending())
|
||||
if (dmaPending() || getState() != Running)
|
||||
goto exit;
|
||||
|
||||
txDmaAddr = params()->platform->pciToDma(
|
||||
@@ -1287,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Device::resume()
|
||||
{
|
||||
SimObject::resume();
|
||||
|
||||
// During drain we could have left the state machines in a waiting state and
|
||||
// they wouldn't get out until some other event occured to kick them.
|
||||
// This way they'll get out immediately
|
||||
txKick();
|
||||
rxKick();
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
//
|
||||
|
||||
@@ -266,6 +266,7 @@ class Device : public Base
|
||||
public:
|
||||
virtual Tick read(Packet *pkt);
|
||||
virtual Tick write(Packet *pkt);
|
||||
virtual void resume();
|
||||
|
||||
void prepareIO(int cpu, int index);
|
||||
void prepareRead(int cpu, int index);
|
||||
|
||||
Reference in New Issue
Block a user