diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/physical.cc | 63 | ||||
-rw-r--r-- | src/mem/physical.hh | 21 | ||||
-rw-r--r-- | src/mem/tport.cc | 82 | ||||
-rw-r--r-- | src/mem/tport.hh | 134 |
4 files changed, 242 insertions, 58 deletions
diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 2d66602ab..291c70d8c 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ron Dreslinski + * Ali Saidi */ #include <sys/types.h> @@ -52,24 +53,6 @@ using namespace std; using namespace TheISA; -PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m) - : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m) -{ - - this->setFlags(AutoDelete); -} - -void -PhysicalMemory::MemResponseEvent::process() -{ - memoryPort->sendTiming(pkt); -} - -const char * -PhysicalMemory::MemResponseEvent::description() -{ - return "Physical Memory Timing Access respnse event"; -} PhysicalMemory::PhysicalMemory(const string &n, Tick latency) : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency) @@ -124,27 +107,8 @@ PhysicalMemory::deviceBlockSize() return 0; } -bool -PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort) -{ - doFunctionalAccess(pkt); - - // turn packet around to go back to requester - pkt->makeTimingResponse(); - MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort); - response->schedule(curTick + lat); - - return true; -} Tick -PhysicalMemory::doAtomicAccess(Packet *pkt) -{ - doFunctionalAccess(pkt); - return lat; -} - -void PhysicalMemory::doFunctionalAccess(Packet *pkt) { assert(pkt->getAddr() + pkt->getSize() < pmem_size); @@ -170,6 +134,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt) } pkt->result = Packet::Success; + return lat; } Port * @@ -195,7 +160,7 @@ PhysicalMemory::recvStatusChange(Port::Status status) PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, PhysicalMemory *_memory) - : Port(_name), memory(_memory) + : SimpleTimingPort(_name), memory(_memory) { } void @@ -228,13 +193,20 @@ PhysicalMemory::MemoryPort::deviceBlockSize() bool PhysicalMemory::MemoryPort::recvTiming(Packet *pkt) { - return memory->doTimingAccess(pkt, this); + assert(pkt->result != Packet::Nacked); + + Tick latency = memory->doFunctionalAccess(pkt); + + pkt->makeTimingResponse(); + sendTiming(pkt, latency); + + return true; } Tick PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) { - return memory->doAtomicAccess(pkt); + return memory->doFunctionalAccess(pkt); } void @@ -243,7 +215,16 @@ PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) memory->doFunctionalAccess(pkt); } - +unsigned int +PhysicalMemory::drain(Event *de) +{ + int count = port->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} void PhysicalMemory::serialize(ostream &os) diff --git a/src/mem/physical.hh b/src/mem/physical.hh index 50fa75ed3..b549c1f8b 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -37,7 +37,7 @@ #include "base/range.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" -#include "mem/port.hh" +#include "mem/tport.hh" #include "sim/eventq.hh" #include <map> #include <string> @@ -47,7 +47,7 @@ // class PhysicalMemory : public MemObject { - class MemoryPort : public Port + class MemoryPort : public SimpleTimingPort { PhysicalMemory *memory; @@ -74,16 +74,6 @@ class PhysicalMemory : public MemObject int numPorts; - struct MemResponseEvent : public Event - { - Packet *pkt; - MemoryPort *memoryPort; - - MemResponseEvent(Packet *pkt, MemoryPort *memoryPort); - void process(); - const char *description(); - }; - private: // prevent copying of a MainMemory object PhysicalMemory(const PhysicalMemory &specmem); @@ -110,13 +100,10 @@ class PhysicalMemory : public MemObject void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); virtual Port *getPort(const std::string &if_name, int idx = -1); void virtual init(); + unsigned int drain(Event *de); - // fast back-door memory access for vtophys(), remote gdb, etc. - // uint64_t phys_read_qword(Addr addr) const; private: - bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort); - Tick doAtomicAccess(Packet *pkt); - void doFunctionalAccess(Packet *pkt); + Tick doFunctionalAccess(Packet *pkt); void recvStatusChange(Port::Status status); diff --git a/src/mem/tport.cc b/src/mem/tport.cc new file mode 100644 index 000000000..90cf68f02 --- /dev/null +++ b/src/mem/tport.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006 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: Ali Saidi + */ + +#include "mem/tport.hh" + +void +SimpleTimingPort::recvRetry() +{ + bool result = true; + while (result && transmitList.size()) { + result = Port::sendTiming(transmitList.front()); + if (result) + transmitList.pop_front(); + } + if (transmitList.size() == 0 && drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } +} + +void +SimpleTimingPort::SendEvent::process() +{ + port->outTiming--; + assert(port->outTiming >= 0); + if (port->Port::sendTiming(packet)) + if (port->transmitList.size() == 0 && port->drainEvent) { + port->drainEvent->process(); + port->drainEvent = NULL; + } + return; + + port->transmitList.push_back(packet); +} + +void +SimpleTimingPort::resendNacked(Packet *pkt) { + pkt->reinitNacked(); + if (transmitList.size()) { + transmitList.push_front(pkt); + } else { + if (!Port::sendTiming(pkt)) + transmitList.push_front(pkt); + } +}; + + +unsigned int +SimpleTimingPort::drain(Event *de) +{ + if (outTiming == 0 && transmitList.size() == 0) + return 0; + drainEvent = de; + return 1; +} diff --git a/src/mem/tport.hh b/src/mem/tport.hh new file mode 100644 index 000000000..5473e945e --- /dev/null +++ b/src/mem/tport.hh @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2006 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: Ali Saidi + */ + +/** + * @file + * Implement a port which adds simple support of a sendTiming() function that + * takes a 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. + */ + +/** recvTiming and drain should be implemented something like this when this + * class is used. + +bool +PioPort::recvTiming(Packet *pkt) +{ + if (pkt->result == Packet::Nacked) { + resendNacked(pkt); + } else { + Tick latency = device->recvAtomic(pkt); + // turn packet around to go back to requester + pkt->makeTimingResponse(); + sendTiming(pkt, latency); + } + return true; +} + +PioDevice::drain(Event *de) +{ + unsigned int count; + count = SimpleTimingPort->drain(de); + if (count) + changeState(Draining); + else + changeState(Drained); + return count; +} +*/ + +#ifndef __MEM_TPORT_HH__ +#define __MEM_TPORT_HH__ + +#include "mem/port.hh" +#include "sim/eventq.hh" +#include <list> +#include <string> + +class SimpleTimingPort : public Port +{ + protected: + /** A list of outgoing timing response packets that haven't been serviced + * yet. */ + std::list<Packet*> transmitList; + /** + * 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 + { + SimpleTimingPort *port; + Packet *packet; + + SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t) + : Event(&mainEventQueue), port(p), packet(pkt) + { setFlags(AutoDelete); schedule(curTick + t); } + + virtual void process(); + + virtual const char *description() + { return "Future scheduled sendTiming event"; } + + friend class SimpleTimingPort; + }; + + + /** 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) + { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); } + + /** This function is notification that the device should attempt to send a + * packet again. */ + virtual void recvRetry(); + + void resendNacked(Packet *pkt); + public: + + SimpleTimingPort(std::string pname) + : Port(pname), outTiming(0), drainEvent(NULL) + {} + + unsigned int drain(Event *de); + + friend class SimpleTimingPort::SendEvent; +}; + +#endif // __MEM_TPORT_HH__ |