X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Ftport.hh;h=5e80f4fab081d5dd6ecee7a44f1abb25bf22193e;hb=f49830ce0ba79c54c65c9c4b25bc3c6184aaf2a9;hp=d720f227c5df621ae21597cc17e4f05e7d2a0c94;hpb=0cd0a8fdd3dc1e329673e2c034e67c2694a6908e;p=gem5.git diff --git a/src/mem/tport.hh b/src/mem/tport.hh index d720f227c..5e80f4fab 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -50,160 +50,61 @@ * Declaration of SimpleTimingPort. */ -#include -#include - -#include "mem/port.hh" -#include "sim/eventq.hh" +#include "mem/qport.hh" /** - * A simple port for interfacing objects that basically have only - * functional memory behavior (e.g. I/O devices) to the memory system. - * Both timing and functional accesses are implemented in terms of - * atomic accesses. A derived port class thus only needs to provide - * recvAtomic() to support all memory access modes. - * - * The tricky part is handling recvTiming(), where the response must - * be scheduled separately via a later call to sendTiming(). This - * feature is handled by scheduling an internal event that calls - * sendTiming() after a delay, and optionally rescheduling the - * response if it is nacked. + * The simple timing port uses a queued port to implement + * recvFunctional and recvTimingReq through recvAtomic. It is always a + * slave port. */ -class SimpleTimingPort : public Port +class SimpleTimingPort : public QueuedSlavePort { - protected: - /** A deferred packet, buffered to transmit later. */ - class DeferredPacket { - public: - Tick tick; ///< The tick when the packet is ready to transmit - PacketPtr pkt; ///< Pointer to the packet to transmit - DeferredPacket(Tick t, PacketPtr p) - : tick(t), pkt(p) - {} - }; - - typedef std::list DeferredPacketList; - typedef std::list::iterator DeferredPacketIterator; - - /** A list of outgoing timing response packets that haven't been - * serviced yet. */ - DeferredPacketList transmitList; - - /** Label to use for print request packets label stack. */ - const std::string label; - - /** This function attempts to send deferred packets. Scheduled to - * be called in the future via SendEvent. */ - void processSendEvent(); - - /** - * This class is used to implemented sendTiming() with a delay. When - * a delay is requested a the event is scheduled if it isn't already. - * When the event time expires it attempts to send the packet. - * If it cannot, the packet sent when recvRetry() is called. - **/ - EventWrapper sendEvent; - - /** If we need to drain, keep the drain event around until we're done - * here.*/ - Event *drainEvent; - - /** Remember whether we're awaiting a retry from the bus. */ - bool waitingOnRetry; - /** Check whether we have a packet ready to go on the transmit list. */ - bool deferredPacketReady() - { return !transmitList.empty() && transmitList.front().tick <= curTick(); } - - Tick deferredPacketReadyTime() - { return transmitList.empty() ? MaxTick : transmitList.front().tick; } + private: /** - * Schedule a send even if not already waiting for a retry. If the - * requested time is before an already scheduled send event it - * will be rescheduled. - * - * @param when + * The packet queue used to store outgoing responses. Note that + * the queue is made private and that we avoid overloading the + * name used in the QueuedSlavePort. Access is provided through + * the queue reference in the base class. */ - void schedSendEvent(Tick when); + SlavePacketQueue queueImpl; - /** Schedule a sendTiming() event to be called in the future. - * @param pkt packet to send - * @param absolute time (in ticks) to send packet - */ - void schedSendTiming(PacketPtr pkt, Tick when); + protected: - /** Attempt to send the packet at the head of the deferred packet - * list. Caller must guarantee that the deferred packet list is - * non-empty and that the head packet is scheduled for curTick() (or - * earlier). - */ - virtual void sendDeferredPacket(); + /** Implemented using recvAtomic(). */ + void recvFunctional(PacketPtr pkt); - /** - * Attempt to send the packet at the front of the transmit list, - * and set waitingOnRetry accordingly. The packet is temporarily - * taken off the list, but put back at the front if not - * successfully sent. - */ - void trySendTiming(); + /** Implemented using recvAtomic(). */ + bool recvTimingReq(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt) = 0; /** - * Based on the transmit list, or the provided time, schedule a - * send event if there are packets to send. If we are idle and - * asked to drain then do so. - * - * @param time an alternative time for the next send event + * @todo this is a temporary workaround until the 4-phase code is committed. + * upstream caches need this packet until true is returned, so hold it for + * deletion until a subsequent call */ - void scheduleSend(Tick time = MaxTick); + std::vector pendingDelete; - /** This function is notification that the device should attempt to send a - * packet again. */ - virtual void recvRetry(); - /** Implemented using recvAtomic(). */ - void recvFunctional(PacketPtr pkt); - - /** Implemented using recvAtomic(). */ - bool recvTiming(PacketPtr pkt); + public: /** - * Simple ports are generally used as slave ports (i.e. the - * respond to requests) and thus do not expect to receive any - * range changes (as the neighbouring port has a master role and - * do not have any address ranges. A subclass can override the - * default behaviuor if needed. + * Create a new SimpleTimingPort that relies on a packet queue to + * hold responses, and implements recvTimingReq and recvFunctional + * through calls to recvAtomic. Once a request arrives, it is + * passed to recvAtomic, and in the case of a timing access any + * response is scheduled to be sent after the delay of the atomic + * operation. + * + * @param name port name + * @param owner structural owner */ - virtual void recvRangeChange() { } + SimpleTimingPort(const std::string& name, MemObject* owner); + virtual ~SimpleTimingPort() { } - public: - SimpleTimingPort(const std::string &_name, MemObject *_owner, - const std::string _label = "SimpleTimingPort"); - ~SimpleTimingPort(); - - /** Check the list of buffered packets against the supplied - * functional request. */ - bool checkFunctional(PacketPtr pkt); - - /** Hook for draining timing accesses from the system. The - * associated SimObject's drain() functions should be implemented - * something like this when this class is used: - \code - PioDevice::drain(Event *de) - { - unsigned int count; - count = SimpleTimingPort->drain(de); - if (count) - changeState(Draining); - else - changeState(Drained); - return count; - } - \endcode - */ - unsigned int drain(Event *de); }; #endif // __MEM_TPORT_HH__