diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/sparc/process.cc | 1 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 1 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 24 | ||||
-rw-r--r-- | src/cpu/thread_state.cc | 5 | ||||
-rw-r--r-- | src/dev/i8254xGBe.cc | 26 | ||||
-rw-r--r-- | src/dev/ide_ctrl.cc | 6 | ||||
-rw-r--r-- | src/dev/io_device.cc | 87 | ||||
-rw-r--r-- | src/dev/io_device.hh | 25 | ||||
-rw-r--r-- | src/dev/ns_gige.cc | 11 | ||||
-rw-r--r-- | src/dev/pcidev.hh | 2 | ||||
-rw-r--r-- | src/dev/sinic.cc | 11 | ||||
-rw-r--r-- | src/mem/bridge.cc | 189 | ||||
-rw-r--r-- | src/mem/bridge.hh | 57 | ||||
-rw-r--r-- | src/mem/bus.cc | 23 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 8 | ||||
-rw-r--r-- | src/mem/tport.cc | 1 | ||||
-rw-r--r-- | src/mem/translating_port.cc | 17 | ||||
-rw-r--r-- | src/mem/translating_port.hh | 13 | ||||
-rw-r--r-- | src/python/m5/objects/Bridge.py | 7 | ||||
-rw-r--r-- | src/python/m5/objects/Device.py | 6 | ||||
-rw-r--r-- | src/sim/eventq.hh | 17 | ||||
-rw-r--r-- | src/sim/faults.cc | 17 | ||||
-rw-r--r-- | src/sim/process.cc | 27 | ||||
-rw-r--r-- | src/sim/process.hh | 27 | ||||
-rw-r--r-- | src/sim/process_impl.hh | 75 | ||||
-rw-r--r-- | src/sim/pseudo_inst.cc | 10 |
26 files changed, 512 insertions, 181 deletions
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index e4774ab54..d595664a0 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -39,6 +39,7 @@ #include "base/misc.hh" #include "cpu/thread_context.hh" #include "mem/page_table.hh" +#include "sim/process_impl.hh" #include "mem/translating_port.hh" #include "sim/system.hh" diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index e6d1e4921..af7494598 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -95,6 +95,7 @@ #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/translating_port.hh" +#include "sim/process_impl.hh" #include "sim/system.hh" using namespace std; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 45da7c3eb..fa7bb4f86 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -574,10 +574,16 @@ TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt) return true; } - else { - //Snooping a Coherence Request, do nothing - return true; + else if (pkt->result == Packet::Nacked) { + assert(cpu->_status == IcacheWaitResponse); + pkt->reinitNacked(); + if (!sendTiming(pkt)) { + cpu->_status = IcacheRetry; + cpu->ifetch_pkt = pkt; + } } + //Snooping a Coherence Request, do nothing + return true; } void @@ -663,10 +669,16 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) return true; } - else { - //Snooping a coherence req, do nothing - return true; + else if (pkt->result == Packet::Nacked) { + assert(cpu->_status == DcacheWaitResponse); + pkt->reinitNacked(); + if (!sendTiming(pkt)) { + cpu->_status = DcacheRetry; + cpu->dcache_pkt = pkt; + } } + //Snooping a Coherence Request, do nothing + return true; } void diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 4b65ca4b8..be8f822f2 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -169,9 +169,8 @@ ThreadState::getMemPort() return port; /* Use this port to for syscall emulation writes to memory. */ - port = new TranslatingPort(csprintf("%s-%d-funcport", - baseCpu->name(), tid), - process->pTable, false); + port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid), + process, TranslatingPort::NextPage); connectToMemFunc(port); diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 6acd06132..e0272c655 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -727,12 +727,8 @@ IGbE::RxDescCache::pktComplete() if (igbe->regs.rdtr.delay()) { DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", igbe->regs.rdtr.delay() * igbe->intClock()); - if (igbe->rdtrEvent.scheduled()) - igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() * - igbe->intClock()); - else - igbe->rdtrEvent.schedule(curTick + igbe->regs.rdtr.delay() * - igbe->intClock()); + igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() * + igbe->intClock(),true); } if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) { @@ -895,6 +891,7 @@ IGbE::TxDescCache::pktComplete() pktPtr = NULL; DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n"); + enableSm(); return; } @@ -946,12 +943,8 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "Descriptor had IDE set\n"); if (igbe->regs.tidv.idv()) { DPRINTF(EthernetDesc, "setting tidv\n"); - if (igbe->tidvEvent.scheduled()) - igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * - igbe->intClock()); - else - igbe->tidvEvent.schedule(curTick + igbe->regs.tidv.idv() * - igbe->intClock()); + igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * + igbe->intClock(), true); } if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) { @@ -979,6 +972,7 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n"); writeback((igbe->cacheBlockSize()-1)>>4); } + enableSm(); igbe->checkDrain(); } @@ -1158,6 +1152,8 @@ IGbE::txStateMachine() return; } + DPRINTF(EthernetSM, "TXS: Nothing to do, stopping ticking\n"); + txTick = false; } bool @@ -1460,6 +1456,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE) SimObjectParam<System *> system; SimObjectParam<Platform *> platform; + Param<Tick> min_backoff_delay; + Param<Tick> max_backoff_delay; SimObjectParam<PciConfigData *> configdata; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; @@ -1481,6 +1479,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE) INIT_PARAM(system, "System pointer"), INIT_PARAM(platform, "Platform pointer"), + INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"), + INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), @@ -1505,6 +1505,8 @@ CREATE_SIM_OBJECT(IGbE) params->name = getInstanceName(); params->platform = platform; params->system = system; + params->min_backoff_delay = min_backoff_delay; + params->max_backoff_delay = max_backoff_delay; params->configData = configdata; params->busNum = pci_bus; params->deviceNum = pci_dev; diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index 1afad529f..921ba1cd0 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -751,6 +751,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController) SimObjectParam<System *> system; SimObjectParam<Platform *> platform; + Param<Tick> min_backoff_delay; + Param<Tick> max_backoff_delay; SimObjectParam<PciConfigData *> configdata; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; @@ -765,6 +767,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController) INIT_PARAM(system, "System pointer"), INIT_PARAM(platform, "Platform pointer"), + INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"), + INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), @@ -781,6 +785,8 @@ CREATE_SIM_OBJECT(IdeController) params->name = getInstanceName(); params->platform = platform; params->system = system; + params->min_backoff_delay = min_backoff_delay; + params->max_backoff_delay = max_backoff_delay; params->configData = configdata; params->busNum = pci_bus; params->deviceNum = pci_dev; diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index a1285fefc..d430ace72 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -93,7 +93,8 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list) DmaPort::DmaPort(DmaDevice *dev, System *s) : Port(dev->name() + "-dmaport", dev), device(dev), sys(s), - pendingCount(0), actionInProgress(0), drainEvent(NULL) + pendingCount(0), actionInProgress(0), drainEvent(NULL), + backoffTime(0), inRetry(false), backoffEvent(this) { } bool @@ -104,12 +105,24 @@ DmaPort::recvTiming(PacketPtr pkt) if (pkt->result == Packet::Nacked) { DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n", pkt, pkt->senderState, pkt->getAddr()); + + if (backoffTime < device->minBackoffDelay) + backoffTime = device->minBackoffDelay; + else if (backoffTime < device->maxBackoffDelay) + backoffTime <<= 1; + + backoffEvent.reschedule(curTick + backoffTime, true); + + DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime); + pkt->reinitNacked(); - sendDma(pkt, true); + queueDma(pkt, true); } else if (pkt->senderState) { DmaReqState *state; - DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x\n", - pkt, pkt->senderState, pkt->getAddr()); + backoffTime >>= 2; + + DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x size: %#x\n", + pkt, pkt->senderState, pkt->getAddr(), pkt->req->getSize()); state = dynamic_cast<DmaReqState*>(pkt->senderState); pendingCount--; @@ -117,6 +130,7 @@ DmaPort::recvTiming(PacketPtr pkt) assert(state); state->numBytes += pkt->req->getSize(); + assert(state->totBytes >= state->numBytes); if (state->totBytes == state->numBytes) { state->completionEvent->process(); delete state; @@ -136,7 +150,8 @@ DmaPort::recvTiming(PacketPtr pkt) } DmaDevice::DmaDevice(Params *p) - : PioDevice(p), dmaPort(NULL) + : PioDevice(p), dmaPort(NULL), minBackoffDelay(p->min_backoff_delay), + maxBackoffDelay(p->max_backoff_delay) { } @@ -165,19 +180,31 @@ DmaPort::drain(Event *de) void DmaPort::recvRetry() { + assert(transmitList.size()); PacketPtr pkt = transmitList.front(); bool result = true; - while (result && transmitList.size()) { + do { DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n", pkt, pkt->senderState); result = sendTiming(pkt); if (result) { DPRINTF(DMA, "-- Done\n"); transmitList.pop_front(); + inRetry = false; } else { + inRetry = true; DPRINTF(DMA, "-- Failed, queued\n"); } + } while (!backoffTime && result && transmitList.size()); + + if (transmitList.size() && backoffTime && !inRetry) { + DPRINTF(DMA, "Scheduling backoff for %d\n", curTick+backoffTime); + if (!backoffEvent.scheduled()) + backoffEvent.schedule(backoffTime+curTick); } + DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n", + transmitList.size(), backoffTime, inRetry, + backoffEvent.scheduled()); } @@ -204,33 +231,61 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, assert(pendingCount >= 0); pendingCount++; - sendDma(pkt); + queueDma(pkt); } } +void +DmaPort::queueDma(PacketPtr pkt, bool front) +{ + + if (front) + transmitList.push_front(pkt); + else + transmitList.push_back(pkt); + sendDma(); +} + void -DmaPort::sendDma(PacketPtr pkt, bool front) +DmaPort::sendDma() { // some kind of selction between access methods // more work is going to have to be done to make // switching actually work + assert(transmitList.size()); + PacketPtr pkt = transmitList.front(); System::MemoryMode state = sys->getMemoryMode(); if (state == System::Timing) { + if (backoffEvent.scheduled() || inRetry) { + DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n"); + return; + } + 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"); + + bool result; + do { + result = sendTiming(pkt); + if (result) { + transmitList.pop_front(); + DPRINTF(DMA, "-- Done\n"); + } else { + inRetry = true; + DPRINTF(DMA, "-- Failed: queued\n"); + } + } while (result && !backoffTime && transmitList.size()); + + if (transmitList.size() && backoffTime && !inRetry && + !backoffEvent.scheduled()) { + backoffEvent.schedule(backoffTime+curTick); } } else if (state == System::Atomic) { + transmitList.pop_front(); + Tick lat; lat = sendAtomic(pkt); assert(pkt->senderState); diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index cd7a5296a..bd150bfe4 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -107,6 +107,14 @@ class DmaPort : public Port * here.*/ Event *drainEvent; + /** time to wait between sending another packet, increases as NACKs are + * recived, decreases as responses are recived. */ + Tick backoffTime; + + /** If the port is currently waiting for a retry before it can send whatever + * it is that it's sending. */ + bool inRetry; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt) { panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN } @@ -122,7 +130,11 @@ class DmaPort : public Port AddrRangeList &snoop) { resp.clear(); snoop.clear(); } - void sendDma(PacketPtr pkt, bool front = false); + void queueDma(PacketPtr pkt, bool front = false); + void sendDma(); + + /** event to give us a kick every time we backoff time is reached. */ + EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent; public: DmaPort(DmaDevice *dev, System *s); @@ -249,8 +261,17 @@ class BasicPioDevice : public PioDevice class DmaDevice : public PioDevice { - protected: + public: + struct Params : public PioDevice::Params + { + Tick min_backoff_delay; + Tick max_backoff_delay; + }; + + protected: DmaPort *dmaPort; + Tick minBackoffDelay; + Tick maxBackoffDelay; public: DmaDevice(Params *p); diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 86f56b62e..d9985f808 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -2310,10 +2310,7 @@ NSGigE::transferDone() DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - if (txEvent.scheduled()) - txEvent.reschedule(curTick + cycles(1)); - else - txEvent.schedule(curTick + cycles(1)); + txEvent.reschedule(curTick + cycles(1), true); } bool @@ -2812,6 +2809,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) SimObjectParam<System *> system; SimObjectParam<Platform *> platform; + Param<Tick> min_backoff_delay; + Param<Tick> max_backoff_delay; SimObjectParam<PciConfigData *> configdata; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; @@ -2846,6 +2845,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) INIT_PARAM(system, "System pointer"), INIT_PARAM(platform, "Platform pointer"), + INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"), + INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), @@ -2884,6 +2885,8 @@ CREATE_SIM_OBJECT(NSGigE) params->name = getInstanceName(); params->platform = platform; params->system = system; + params->min_backoff_delay = min_backoff_delay; + params->max_backoff_delay = max_backoff_delay; params->configData = configdata; params->busNum = pci_bus; params->deviceNum = pci_dev; diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index 56e3ffb4a..5044e2932 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -105,7 +105,7 @@ class PciDev : public DmaDevice }; public: - struct Params : public PioDevice::Params + struct Params : public DmaDevice::Params { /** * A pointer to the object that contains the first 64 bytes of diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index f61c161aa..420761620 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -1199,10 +1199,7 @@ Device::transferDone() DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - if (txEvent.scheduled()) - txEvent.reschedule(curTick + cycles(1)); - else - txEvent.schedule(curTick + cycles(1)); + txEvent.reschedule(curTick + cycles(1), true); } bool @@ -1635,6 +1632,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice) SimObjectParam<System *> system; SimObjectParam<Platform *> platform; + Param<Tick> min_backoff_delay; + Param<Tick> max_backoff_delay; SimObjectParam<PciConfigData *> configdata; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; @@ -1678,6 +1677,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice) INIT_PARAM(system, "System pointer"), INIT_PARAM(platform, "Platform pointer"), + INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"), + INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_dev, "PCI device number"), @@ -1723,6 +1724,8 @@ CREATE_SIM_OBJECT_WNS(Sinic, SinicDevice) params->name = getInstanceName(); params->platform = platform; params->system = system; + params->min_backoff_delay = min_backoff_delay; + params->max_backoff_delay = max_backoff_delay; params->configData = configdata; params->busNum = pci_bus; params->deviceNum = pci_dev; diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index b25d135e2..e89473be3 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -43,21 +43,22 @@ Bridge::BridgePort::BridgePort(const std::string &_name, Bridge *_bridge, BridgePort *_otherPort, - int _delay, int _queueLimit, - bool fix_partial_write) + int _delay, int _nack_delay, int _req_limit, + int _resp_limit, bool fix_partial_write) : Port(_name), bridge(_bridge), otherPort(_otherPort), - delay(_delay), fixPartialWrite(fix_partial_write), - outstandingResponses(0), queueLimit(_queueLimit), sendEvent(this) + delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write), + outstandingResponses(0), queuedRequests(0), inRetry(false), + reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) { } -Bridge::Bridge(const std::string &n, int qsa, int qsb, - Tick _delay, int write_ack, bool fix_partial_write_a, - bool fix_partial_write_b) - : MemObject(n), - portA(n + "-portA", this, &portB, _delay, qsa, fix_partial_write_a), - portB(n + "-portB", this, &portA, _delay, qsa, fix_partial_write_b), - ackWrites(write_ack) +Bridge::Bridge(Params *p) + : MemObject(p->name), + portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay, + p->req_size_a, p->resp_size_a, p->fix_partial_write_a), + portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay, + p->req_size_b, p->resp_size_b, p->fix_partial_write_b), + ackWrites(p->write_ack), _params(p) { if (ackWrites) panic("No support for acknowledging writes\n"); @@ -92,34 +93,105 @@ Bridge::init() fatal("Busses don't have the same block size... Not supported.\n"); } +bool +Bridge::BridgePort::respQueueFull() +{ + assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); + return outstandingResponses >= respQueueLimit; +} + +bool +Bridge::BridgePort::reqQueueFull() +{ + assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); + return queuedRequests >= reqQueueLimit; +} /** Function called by the port when the bus is receiving a Timing * transaction.*/ bool Bridge::BridgePort::recvTiming(PacketPtr pkt) { - if (pkt->flags & SNOOP_COMMIT) { - DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", + if (!(pkt->flags & SNOOP_COMMIT)) + return true; + + + DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr()); - return otherPort->queueForSendTiming(pkt); + if (pkt->isRequest() && otherPort->reqQueueFull()) { + DPRINTF(BusBridge, "Remote queue full, nacking\n"); + nackRequest(pkt); + return true; + } + + if (pkt->needsResponse() && pkt->result != Packet::Nacked) + if (respQueueFull()) { + DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); + DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", + sendQueue.size(), queuedRequests, outstandingResponses); + nackRequest(pkt); + return true; + } else { + DPRINTF(BusBridge, "Request Needs response, reserving space\n"); + ++outstandingResponses; + } + + otherPort->queueForSendTiming(pkt); + + return true; +} + +void +Bridge::BridgePort::nackRequest(PacketPtr pkt) +{ + // Nack the packet + pkt->result = Packet::Nacked; + pkt->setDest(pkt->getSrc()); + + //put it on the list to send + Tick readyTime = curTick + nackDelay; + PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); + + // nothing on the list, add it and we're done + if (sendQueue.empty()) { + assert(!sendEvent.scheduled()); + sendEvent.schedule(readyTime); + sendQueue.push_back(buf); + return; + } + + assert(sendEvent.scheduled() || inRetry); + + // does it go at the end? + if (readyTime >= sendQueue.back()->ready) { + sendQueue.push_back(buf); + return; } - else { - // Else it's just a snoop, properly return if we are blocking - return !queueFull(); + + // ok, somewhere in the middle, fun + std::list<PacketBuffer*>::iterator i = sendQueue.begin(); + std::list<PacketBuffer*>::iterator end = sendQueue.end(); + std::list<PacketBuffer*>::iterator begin = sendQueue.begin(); + bool done = false; + + while (i != end && !done) { + if (readyTime < (*i)->ready) { + if (i == begin) + sendEvent.reschedule(readyTime); + sendQueue.insert(i,buf); + done = true; + } + i++; } + assert(done); } -bool +void Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) { - if (queueFull()) { - DPRINTF(BusBridge, "Queue full, returning false\n"); - return false; - } - - if (pkt->isResponse()) { + if (pkt->isResponse() || pkt->result == Packet::Nacked) { // This is a response for a request we forwarded earlier. The // corresponding PacketBuffer should be stored in the packet's // senderState field. @@ -128,6 +200,13 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) // set up new packet dest & senderState based on values saved // from original request buf->fixResponse(pkt); + + // Check if this packet was expecting a response (this is either it or + // its a nacked packet and we won't be seeing that response) + if (buf->expectResponse) + --outstandingResponses; + + DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", pkt->senderState, buf); DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); @@ -146,10 +225,8 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) if (sendQueue.empty()) { sendEvent.schedule(readyTime); } - + ++queuedRequests; sendQueue.push_back(buf); - - return true; } void @@ -157,7 +234,6 @@ Bridge::BridgePort::trySend() { assert(!sendQueue.empty()); - bool was_full = queueFull(); int pbs = peerBlockSize(); PacketBuffer *buf = sendQueue.front(); @@ -169,7 +245,8 @@ Bridge::BridgePort::trySend() pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && - pkt->getOffset(pbs) && pkt->getSize() != pbs) { + pkt->result != Packet::Nacked && pkt->getOffset(pbs) && + pkt->getSize() != pbs) { buf->partialWriteFix(this); pkt = buf->pkt; } @@ -184,10 +261,7 @@ Bridge::BridgePort::trySend() buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it if (buf->expectResponse) { - // Must wait for response. We just need to count outstanding - // responses (in case we want to cap them); PacketBuffer - // pointer will be recovered on response. - ++outstandingResponses; + // Must wait for response DPRINTF(BusBridge, " successful: awaiting response (%d)\n", outstandingResponses); } else { @@ -196,28 +270,34 @@ Bridge::BridgePort::trySend() delete buf; } + if (!buf->nacked) + --queuedRequests; + // If there are more packets to send, schedule event to try again. if (!sendQueue.empty()) { buf = sendQueue.front(); + DPRINTF(BusBridge, "Scheduling next send\n"); sendEvent.schedule(std::max(buf->ready, curTick + 1)); } - // Let things start sending again - if (was_full) { - DPRINTF(BusBridge, "Queue was full, sending retry\n"); - otherPort->sendRetry(); - } - } else { DPRINTF(BusBridge, " unsuccessful\n"); buf->undoPartialWriteFix(); + inRetry = true; } + DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", + sendQueue.size(), queuedRequests, outstandingResponses); } void Bridge::BridgePort::recvRetry() { - trySend(); + inRetry = false; + Tick nextReady = sendQueue.front()->ready; + if (nextReady <= curTick) + trySend(); + else + sendEvent.schedule(nextReady); } /** Function called by the port when the bus is receiving a Atomic @@ -263,9 +343,12 @@ Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) - Param<int> queue_size_a; - Param<int> queue_size_b; + Param<int> req_size_a; + Param<int> req_size_b; + Param<int> resp_size_a; + Param<int> resp_size_b; Param<Tick> delay; + Param<Tick> nack_delay; Param<bool> write_ack; Param<bool> fix_partial_write_a; Param<bool> fix_partial_write_b; @@ -274,9 +357,12 @@ END_DECLARE_SIM_OBJECT_PARAMS(Bridge) BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) - INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"), - INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"), + INIT_PARAM(req_size_a, "The size of the queue for requests coming into side a"), + INIT_PARAM(req_size_b, "The size of the queue for requests coming into side b"), + INIT_PARAM(resp_size_a, "The size of the queue for responses coming into side a"), + INIT_PARAM(resp_size_b, "The size of the queue for responses coming into side b"), INIT_PARAM(delay, "The miminum delay to cross this bridge"), + INIT_PARAM(nack_delay, "The minimum delay to nack a packet"), INIT_PARAM(write_ack, "Acknowledge any writes that are received."), INIT_PARAM(fix_partial_write_a, "Fixup any partial block writes that are received"), INIT_PARAM(fix_partial_write_b, "Fixup any partial block writes that are received") @@ -285,8 +371,19 @@ END_INIT_SIM_OBJECT_PARAMS(Bridge) CREATE_SIM_OBJECT(Bridge) { - return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, - write_ack, fix_partial_write_a, fix_partial_write_b); + Bridge::Params *p = new Bridge::Params; + p->name = getInstanceName(); + p->req_size_a = req_size_a; + p->req_size_b = req_size_b; + p->resp_size_a = resp_size_a; + p->resp_size_b = resp_size_b; + p->delay = delay; + p->nack_delay = nack_delay; + p->write_ack = write_ack; + p->fix_partial_write_a = fix_partial_write_a; + p->fix_partial_write_b = fix_partial_write_b; + return new Bridge(p); } REGISTER_SIM_OBJECT("Bridge", Bridge) + diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index d1154eda0..cb5a6baed 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -66,6 +66,9 @@ class Bridge : public MemObject /** Minimum delay though this bridge. */ Tick delay; + /** Min delay to respond to a nack. */ + Tick nackDelay; + bool fixPartialWrite; class PacketBuffer : public Packet::SenderState { @@ -79,13 +82,16 @@ class Bridge : public MemObject bool partialWriteFixed; PacketPtr oldPkt; + bool nacked; - PacketBuffer(PacketPtr _pkt, Tick t) + PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false) : ready(t), pkt(_pkt), origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()), - expectResponse(_pkt->needsResponse()), partialWriteFixed(false) + expectResponse(_pkt->needsResponse() && !nack), + partialWriteFixed(false), nacked(nack) + { - if (!pkt->isResponse()) + if (!pkt->isResponse() && !nack) pkt->senderState = this; } @@ -144,19 +150,29 @@ class Bridge : public MemObject std::list<PacketBuffer*> sendQueue; int outstandingResponses; + int queuedRequests; + + /** If we're waiting for a retry to happen.*/ + bool inRetry; /** Max queue size for outbound packets */ - int queueLimit; + int reqQueueLimit; + + /** Max queue size for reserved responses. */ + int respQueueLimit; /** * Is this side blocked from accepting outbound packets? */ - bool queueFull() { return (sendQueue.size() == queueLimit); } + bool respQueueFull(); + bool reqQueueFull(); - bool queueForSendTiming(PacketPtr pkt); + void queueForSendTiming(PacketPtr pkt); void finishSend(PacketBuffer *buf); + void nackRequest(PacketPtr pkt); + /** * Handle send event, scheduled when the packet at the head of * the outbound queue is ready to transmit (for timing @@ -180,11 +196,10 @@ class Bridge : public MemObject SendEvent sendEvent; public: - /** Constructor for the BusPort.*/ - BridgePort(const std::string &_name, - Bridge *_bridge, BridgePort *_otherPort, - int _delay, int _queueLimit, bool fix_partial_write); + BridgePort(const std::string &_name, Bridge *_bridge, + BridgePort *_otherPort, int _delay, int _nack_delay, + int _req_limit, int _resp_limit, bool fix_partial_write); protected: @@ -220,14 +235,32 @@ class Bridge : public MemObject bool ackWrites; public: + struct Params + { + std::string name; + int req_size_a; + int req_size_b; + int resp_size_a; + int resp_size_b; + Tick delay; + Tick nack_delay; + bool write_ack; + bool fix_partial_write_a; + bool fix_partial_write_b; + }; + + protected: + Params *_params; + + public: + const Params *params() const { return _params; } /** A function used to return the port associated with this bus object. */ virtual Port *getPort(const std::string &if_name, int idx = -1); virtual void init(); - Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack, - bool fix_partial_write_a, bool fix_partial_write_b); + Bridge(Params *p); }; #endif //__MEM_BUS_HH__ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 6682ade55..95d4e2873 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -171,8 +171,9 @@ bool Bus::recvTiming(PacketPtr pkt) { Port *port; - DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n", - pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); + DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s result %d\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString(), + pkt->result); BusPort *pktPort; if (pkt->getSrc() == defaultId) @@ -272,20 +273,14 @@ Bus::recvRetry(int id) retryList.pop_front(); inRetry = false; - if (id != -1) { - //Bring tickNextIdle up to the present - while (tickNextIdle < curTick) - tickNextIdle += clock; - - //Burn a cycle for the missed grant. + //Bring tickNextIdle up to the present + while (tickNextIdle < curTick) tickNextIdle += clock; - if (!busIdle.scheduled()) { - busIdle.schedule(tickNextIdle); - } else { - busIdle.reschedule(tickNextIdle); - } - } // id != -1 + //Burn a cycle for the missed grant. + tickNextIdle += clock; + + busIdle.reschedule(tickNextIdle, true); } } //If we weren't able to drain before, we might be able to now. diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 0a528aa5d..c70f10151 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1192,6 +1192,8 @@ template<class TagStore, class Coherence> bool Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt) { + assert(pkt->result != Packet::Nacked); + if (!pkt->req->isUncacheable() && pkt->isInvalidate() && !pkt->isRead() && !pkt->isWrite()) { @@ -1249,6 +1251,12 @@ template<class TagStore, class Coherence> bool Cache<TagStore,Coherence>::MemSidePort::recvTiming(PacketPtr pkt) { + // this needs to be fixed so that the cache updates the mshr and sends the + // packet back out on the link, but it probably won't happen so until this + // gets fixed, just panic when it does + if (pkt->result == Packet::Nacked) + panic("Need to implement cache resending nacked packets!\n"); + if (pkt->isRequest() && blocked) { DPRINTF(Cache,"Scheduling a retry while blocked\n"); diff --git a/src/mem/tport.cc b/src/mem/tport.cc index b384a0444..9a4bd7967 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -128,6 +128,7 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) } i++; } + assert(done); } void diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc index d2c854086..54de6625e 100644 --- a/src/mem/translating_port.cc +++ b/src/mem/translating_port.cc @@ -34,12 +34,14 @@ #include "mem/port.hh" #include "mem/translating_port.hh" #include "mem/page_table.hh" +#include "sim/process.hh" using namespace TheISA; TranslatingPort::TranslatingPort(const std::string &_name, - PageTable *p_table, bool alloc) - : FunctionalPort(_name), pTable(p_table), allocating(alloc) + Process *p, AllocType alloc) + : FunctionalPort(_name), pTable(p->pTable), process(p), + allocating(alloc) { } TranslatingPort::~TranslatingPort() @@ -81,13 +83,18 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { if (!pTable->translate(gen.addr(), paddr)) { - if (allocating) { + if (allocating == Always) { pTable->allocate(roundDown(gen.addr(), VMPageSize), VMPageSize); - pTable->translate(gen.addr(), paddr); + } else if (allocating == NextPage) { + // check if we've accessed the next page on the stack + if (!process->checkAndAllocNextPage(gen.addr())) + panic("Page table fault when accessing virtual address %#x " + "during functional write\n", gen.addr()); } else { return false; } + pTable->translate(gen.addr(), paddr); } Port::writeBlob(paddr, p + prevSize, gen.size()); @@ -113,7 +120,7 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size) for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { if (!pTable->translate(gen.addr(), paddr)) { - if (allocating) { + if (allocating == Always) { pTable->allocate(roundDown(gen.addr(), VMPageSize), VMPageSize); pTable->translate(gen.addr(), paddr); diff --git a/src/mem/translating_port.hh b/src/mem/translating_port.hh index 7354278ba..76c7947be 100644 --- a/src/mem/translating_port.hh +++ b/src/mem/translating_port.hh @@ -35,16 +35,25 @@ #include "mem/port.hh" class PageTable; +class Process; class TranslatingPort : public FunctionalPort { + public: + enum AllocType { + Always, + Never, + NextPage + }; + private: PageTable *pTable; - bool allocating; + Process *process; + AllocType allocating; public: TranslatingPort(const std::string &_name, - PageTable *p_table, bool alloc = false); + Process *p, AllocType alloc); virtual ~TranslatingPort(); bool tryReadBlob(Addr addr, uint8_t *p, int size); diff --git a/src/python/m5/objects/Bridge.py b/src/python/m5/objects/Bridge.py index e123c2891..33b24ad3c 100644 --- a/src/python/m5/objects/Bridge.py +++ b/src/python/m5/objects/Bridge.py @@ -5,9 +5,12 @@ class Bridge(MemObject): type = 'Bridge' side_a = Port('Side A port') side_b = Port('Side B port') - queue_size_a = Param.Int(16, "The number of requests to buffer") - queue_size_b = Param.Int(16, "The number of requests to buffer") + req_size_a = Param.Int(16, "The number of requests to buffer") + req_size_b = Param.Int(16, "The number of requests to buffer") + resp_size_a = Param.Int(16, "The number of requests to buffer") + resp_size_b = Param.Int(16, "The number of requests to buffer") delay = Param.Latency('0ns', "The latency of this bridge") + nack_delay = Param.Latency('0ns', "The latency of this bridge") write_ack = Param.Bool(False, "Should this bridge ack writes") fix_partial_write_a = Param.Bool(False, "Should this bridge fixup partial block writes") fix_partial_write_b = Param.Bool(False, "Should this bridge fixup partial block writes") diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py index f4b873a60..90fbfb552 100644 --- a/src/python/m5/objects/Device.py +++ b/src/python/m5/objects/Device.py @@ -19,6 +19,12 @@ class DmaDevice(PioDevice): type = 'DmaDevice' abstract = True dma = Port(Self.pio.peerObj.port, "DMA port") + min_backoff_delay = Param.Latency('4ns', + "min time between a nack packet being received and the next request made by the device") + max_backoff_delay = Param.Latency('10us', + "max time between a nack packet being received and the next request made by the device") + + class IsaFake(BasicPioDevice): type = 'IsaFake' diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a57e9077e..974313968 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -210,7 +210,8 @@ class Event : public Serializable, public FastAlloc void schedule(Tick t); /// Reschedule the event with the current priority - void reschedule(Tick t); + // always parameter means to schedule if not already scheduled + void reschedule(Tick t, bool always = false); /// Remove the event from the current schedule void deschedule(); @@ -402,16 +403,22 @@ Event::deschedule() } inline void -Event::reschedule(Tick t) +Event::reschedule(Tick t, bool always) { - assert(scheduled()); - clearFlags(Squashed); + assert(scheduled() || always); #if TRACING_ON when_scheduled = curTick; #endif _when = t; - queue->reschedule(this); + + if (scheduled()) { + clearFlags(Squashed); + queue->reschedule(this); + } else { + setFlags(Scheduled); + queue->schedule(this); + } } inline void diff --git a/src/sim/faults.cc b/src/sim/faults.cc index b09bbc177..fe62874d7 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -61,21 +61,8 @@ void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); - // We've accessed the next page of the stack, so extend the stack - // to cover it. - if(vaddr < p->stack_min && vaddr >= p->stack_min - TheISA::PageBytes) - { - p->stack_min -= TheISA::PageBytes; - if(p->stack_base - p->stack_min > 8*1024*1024) - fatal("Over max stack size for one thread\n"); - p->pTable->allocate(p->stack_min, TheISA::PageBytes); - warn("Increasing stack size by one page."); - } - // Otherwise, we have an unexpected page fault. Report that fact, - // and what address was accessed to cause the fault. - else - { + if (!p->checkAndAllocNextPage(vaddr)) panic("Page table fault when accessing virtual address %#x\n", vaddr); - } + } #endif diff --git a/src/sim/process.cc b/src/sim/process.cc index 68239fa52..8b273d591 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -47,6 +47,7 @@ #include "mem/translating_port.hh" #include "sim/builder.hh" #include "sim/process.hh" +#include "sim/process_impl.hh" #include "sim/stats.hh" #include "sim/syscall_emul.hh" #include "sim/system.hh" @@ -182,7 +183,8 @@ Process::startup() Port *mem_port; mem_port = system->physmem->getPort("functional"); - initVirtMem = new TranslatingPort("process init port", pTable, true); + initVirtMem = new TranslatingPort("process init port", this, + TranslatingPort::Always); mem_port->setPeer(initVirtMem); initVirtMem->setPeer(mem_port); } @@ -250,6 +252,29 @@ Process::sim_fd(int tgt_fd) return fd_map[tgt_fd]; } +bool +Process::checkAndAllocNextPage(Addr vaddr) +{ + // if this is an initial write we might not have + if (vaddr >= stack_min && vaddr < stack_base) { + pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize); + return true; + } + + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if(vaddr < stack_min && vaddr >= stack_min - TheISA::PageBytes) + { + stack_min -= TheISA::PageBytes; + if(stack_base - stack_min > 8*1024*1024) + fatal("Over max stack size for one thread\n"); + pTable->allocate(stack_min, TheISA::PageBytes); + warn("Increasing stack size by one page."); + return true; + } + return false; +} + void Process::serialize(std::ostream &os) { diff --git a/src/sim/process.hh b/src/sim/process.hh index dd64fa607..fa46b9c95 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -45,7 +45,6 @@ #include <vector> #include "base/statistics.hh" -#include "mem/translating_port.hh" #include "sim/host.hh" #include "sim/sim_object.hh" @@ -60,28 +59,6 @@ namespace TheISA class RemoteGDB; } -//This needs to be templated for cases where 32 bit pointers are needed. -template<class AddrType> -void -copyStringArray(std::vector<std::string> &strings, - AddrType array_ptr, AddrType data_ptr, - TranslatingPort* memPort) -{ - AddrType data_ptr_swap; - for (int i = 0; i < strings.size(); ++i) { - data_ptr_swap = htog(data_ptr); - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, - sizeof(AddrType)); - memPort->writeString(data_ptr, strings[i].c_str()); - array_ptr += sizeof(AddrType); - data_ptr += strings[i].size() + 1; - } - // add NULL terminator - data_ptr = 0; - - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); -} - class Process : public SimObject { public: @@ -194,6 +171,10 @@ class Process : public SimObject virtual void syscall(int64_t callnum, ThreadContext *tc) = 0; + // check if the this addr is on the next available page and allocate it + // if it's not we'll panic + bool checkAndAllocNextPage(Addr vaddr); + void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); }; diff --git a/src/sim/process_impl.hh b/src/sim/process_impl.hh new file mode 100644 index 000000000..a3519fe39 --- /dev/null +++ b/src/sim/process_impl.hh @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __SIM_PROCESS_IMPL_HH__ +#define __SIM_PROCESS_IMPL_HH__ + +// +// The purpose of this code is to fake the loader & syscall mechanism +// when there's no OS: thus there's no reason to use it in FULL_SYSTEM +// mode when we do have an OS. +// +#include "config/full_system.hh" + +#if !FULL_SYSTEM + +#include <string> +#include <vector> + +#include "mem/translating_port.hh" + + +//This needs to be templated for cases where 32 bit pointers are needed. +template<class AddrType> +void +copyStringArray(std::vector<std::string> &strings, + AddrType array_ptr, AddrType data_ptr, + TranslatingPort* memPort) +{ + AddrType data_ptr_swap; + for (int i = 0; i < strings.size(); ++i) { + data_ptr_swap = htog(data_ptr); + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, + sizeof(AddrType)); + memPort->writeString(data_ptr, strings[i].c_str()); + array_ptr += sizeof(AddrType); + data_ptr += strings[i].size() + 1; + } + // add NULL terminator + data_ptr = 0; + + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); +} + + +#endif // !FULL_SYSTEM + +#endif diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 56a779674..10127aa5f 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -87,10 +87,7 @@ namespace PseudoInst Tick resume = curTick + Clock::Int::ns * ns; - if (quiesceEvent->scheduled()) - quiesceEvent->reschedule(resume); - else - quiesceEvent->schedule(resume); + quiesceEvent->reschedule(resume, true); DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", tc->getCpuPtr()->name(), ns, resume); @@ -110,10 +107,7 @@ namespace PseudoInst Tick resume = curTick + tc->getCpuPtr()->cycles(cycles); - if (quiesceEvent->scheduled()) - quiesceEvent->reschedule(resume); - else - quiesceEvent->schedule(resume); + quiesceEvent->reschedule(resume, true); DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", tc->getCpuPtr()->name(), cycles, resume); |