From 851f91f2457aabbce2527231b725abf306aa35ff Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 20 Jul 2006 19:03:47 -0400 Subject: [PATCH] Move PioPort timing code into Simple Timing Port object Make PioPort use it Make Physical memory use it as well src/SConscript: Add timing port to sconscript src/dev/io_device.cc: src/dev/io_device.hh: Move simple timing pio port stuff into a simple timing port class so it can be used by the physical memory src/mem/physical.cc: src/mem/physical.hh: use a simple timing port stuff instead of rolling our own here --HG-- extra : convert_revision : e5befbd295a572568cfdca533efb5ed1984c59d1 --- src/SConscript | 1 + src/dev/io_device.cc | 54 +---------------- src/dev/io_device.hh | 59 ++----------------- src/mem/physical.cc | 63 +++++++------------- src/mem/physical.hh | 21 ++----- src/mem/tport.cc | 82 ++++++++++++++++++++++++++ src/mem/tport.hh | 134 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 248 insertions(+), 166 deletions(-) create mode 100644 src/mem/tport.cc create mode 100644 src/mem/tport.hh diff --git a/src/SConscript b/src/SConscript index 9825cafe7..5e61b285b 100644 --- a/src/SConscript +++ b/src/SConscript @@ -98,6 +98,7 @@ base_sources = Split(''' mem/packet.cc mem/physical.cc mem/port.cc + mem/tport.cc mem/cache/base_cache.cc mem/cache/cache.cc diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 660efabfd..b51a93190 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -36,8 +36,7 @@ PioPort::PioPort(PioDevice *dev, System *s, std::string pname) - : Port(dev->name() + pname), device(dev), sys(s), - outTiming(0), drainEvent(NULL) + : SimpleTimingPort(dev->name() + pname), device(dev), sys(s) { } @@ -61,48 +60,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) } -void -PioPort::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 -PioPort::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 -PioPort::resendNacked(Packet *pkt) { - pkt->reinitNacked(); - if (transmitList.size()) { - transmitList.push_front(pkt); - } else { - if (!Port::sendTiming(pkt)) - transmitList.push_front(pkt); - } -}; - - bool PioPort::recvTiming(Packet *pkt) { @@ -117,15 +74,6 @@ 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) diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index fa3f98247..22a32e73a 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -37,6 +37,7 @@ #include "mem/packet_impl.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" +#include "mem/tport.hh" class Platform; class PioDevice; @@ -48,13 +49,9 @@ class System; * 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 + * with which it returns the address ranges it is interested in. */ + +class PioPort : public SimpleTimingPort { protected: /** The device that this port serves. */ @@ -64,10 +61,6 @@ class PioPort : public Port * we are currently operating in. */ System *sys; - /** A list of outgoing timing response packets that haven't been serviced - * yet. */ - std::list transmitList; - /** The current status of the peer(bus) that we are connected to. */ Status peerStatus; @@ -82,53 +75,9 @@ class PioPort : public Port virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); - void resendNacked(Packet *pkt); - - /** - * This class is used to implemented sendTiming() with a delay. When a delay - * is requested a new event is created. When the event time expires it - * attempts to send the packet. If it cannot, the packet is pushed onto the - * transmit list to be sent when recvRetry() is called. */ - class SendEvent : public Event - { - PioPort *port; - Packet *packet; - - SendEvent(PioPort *p, Packet *pkt, Tick t) - : Event(&mainEventQueue), port(p), packet(pkt) - { schedule(curTick + t); } - - virtual void process(); - - virtual const char *description() - { return "Future scheduled sendTiming event"; } - - 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) - { 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, System *s, std::string pname = "-pioport"); - unsigned int drain(Event *de); - - friend class PioPort::SendEvent; }; 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 @@ -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 #include @@ -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 +#include + +class SimpleTimingPort : public Port +{ + protected: + /** A list of outgoing timing response packets that haven't been serviced + * yet. */ + std::list 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__ -- 2.30.2