timing.hh revision 10713
12623SN/A/*
22623SN/A * Copyright (c) 2012-2013 ARM Limited
32623SN/A * All rights reserved
42623SN/A *
52623SN/A * The license below extends only to copyright in the software and shall
62623SN/A * not be construed as granting a license to any other intellectual
72623SN/A * property including but not limited to intellectual property relating
82623SN/A * to a hardware implementation of the functionality of the software
92623SN/A * licensed hereunder.  You may use the software subject to the license
102623SN/A * terms below provided that you ensure that this notice is replicated
112623SN/A * unmodified and in its entirety in all distributions of the software,
122623SN/A * modified or unmodified, in source code or in binary form.
132623SN/A *
142623SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
152623SN/A * All rights reserved.
162623SN/A *
172623SN/A * Redistribution and use in source and binary forms, with or without
182623SN/A * modification, are permitted provided that the following conditions are
192623SN/A * met: redistributions of source code must retain the above copyright
202623SN/A * notice, this list of conditions and the following disclaimer;
212623SN/A * redistributions in binary form must reproduce the above copyright
222623SN/A * notice, this list of conditions and the following disclaimer in the
232623SN/A * documentation and/or other materials provided with the distribution;
242623SN/A * neither the name of the copyright holders nor the names of its
252623SN/A * contributors may be used to endorse or promote products derived from
262623SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392623SN/A *
402623SN/A * Authors: Steve Reinhardt
412623SN/A */
422623SN/A
432623SN/A#ifndef __CPU_SIMPLE_TIMING_HH__
442623SN/A#define __CPU_SIMPLE_TIMING_HH__
452623SN/A
462623SN/A#include "cpu/simple/base.hh"
472623SN/A#include "cpu/translation.hh"
482623SN/A#include "params/TimingSimpleCPU.hh"
492623SN/A
502623SN/Aclass TimingSimpleCPU : public BaseSimpleCPU
512623SN/A{
522623SN/A  public:
532623SN/A
542623SN/A    TimingSimpleCPU(TimingSimpleCPUParams * params);
552623SN/A    virtual ~TimingSimpleCPU();
562623SN/A
572623SN/A    virtual void init();
582623SN/A
592623SN/A  private:
602623SN/A
612623SN/A    /*
622623SN/A     * If an access needs to be broken into fragments, currently at most two,
632623SN/A     * the the following two classes are used as the sender state of the
642623SN/A     * packets so the CPU can keep track of everything. In the main packet
652623SN/A     * sender state, there's an array with a spot for each fragment. If a
662623SN/A     * fragment has already been accepted by the CPU, aka isn't waiting for
672839Sktlim@umich.edu     * a retry, it's pointer is NULL. After each fragment has successfully
682798Sktlim@umich.edu     * been processed, the "outstanding" counter is decremented. Once the
692623SN/A     * count is zero, the entire larger access is complete.
702623SN/A     */
712623SN/A    class SplitMainSenderState : public Packet::SenderState
722623SN/A    {
732623SN/A      public:
742623SN/A        int outstanding;
752948Ssaidi@eecs.umich.edu        PacketPtr fragments[2];
762623SN/A
772623SN/A        int
782623SN/A        getPendingFragment()
792948Ssaidi@eecs.umich.edu        {
803401Sktlim@umich.edu            if (fragments[0]) {
812623SN/A                return 0;
822623SN/A            } else if (fragments[1]) {
833647Srdreslin@umich.edu                return 1;
843647Srdreslin@umich.edu            } else {
852623SN/A                return -1;
862623SN/A            }
873349Sbinkertn@umich.edu        }
882623SN/A    };
893349Sbinkertn@umich.edu
902623SN/A    class SplitFragmentSenderState : public Packet::SenderState
912623SN/A    {
922623SN/A      public:
932623SN/A        SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
944475Sstever@eecs.umich.edu            bigPkt(_bigPkt), index(_index)
954475Sstever@eecs.umich.edu        {}
962948Ssaidi@eecs.umich.edu        PacketPtr bigPkt;
972948Ssaidi@eecs.umich.edu        int index;
982948Ssaidi@eecs.umich.edu
993349Sbinkertn@umich.edu        void
1002948Ssaidi@eecs.umich.edu        clearFromParent()
1012948Ssaidi@eecs.umich.edu        {
1022948Ssaidi@eecs.umich.edu            SplitMainSenderState * main_send_state =
1032948Ssaidi@eecs.umich.edu                dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
1044873Sstever@eecs.umich.edu            main_send_state->fragments[index] = NULL;
1053349Sbinkertn@umich.edu        }
1062948Ssaidi@eecs.umich.edu    };
1072948Ssaidi@eecs.umich.edu
1082623SN/A    class FetchTranslation : public BaseTLB::Translation
1092623SN/A    {
1102623SN/A      protected:
1112623SN/A        TimingSimpleCPU *cpu;
1122623SN/A
1132623SN/A      public:
1142948Ssaidi@eecs.umich.edu        FetchTranslation(TimingSimpleCPU *_cpu)
1152948Ssaidi@eecs.umich.edu            : cpu(_cpu)
1162623SN/A        {}
1172623SN/A
1182623SN/A        void
1192623SN/A        markDelayed()
1203349Sbinkertn@umich.edu        {
1212623SN/A            assert(cpu->_status == BaseSimpleCPU::Running);
1222657Ssaidi@eecs.umich.edu            cpu->_status = ITBWaitResponse;
1232948Ssaidi@eecs.umich.edu        }
1242948Ssaidi@eecs.umich.edu
1252948Ssaidi@eecs.umich.edu        void
1262948Ssaidi@eecs.umich.edu        finish(const Fault &fault, RequestPtr req, ThreadContext *tc,
1272948Ssaidi@eecs.umich.edu               BaseTLB::Mode mode)
1282948Ssaidi@eecs.umich.edu        {
1292948Ssaidi@eecs.umich.edu            cpu->sendFetch(fault, req, tc);
1304873Sstever@eecs.umich.edu        }
1312948Ssaidi@eecs.umich.edu    };
1322948Ssaidi@eecs.umich.edu    FetchTranslation fetchTranslation;
1332948Ssaidi@eecs.umich.edu
1342948Ssaidi@eecs.umich.edu    void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
1352623SN/A    void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
1362623SN/A                       uint8_t *data, bool read);
1372623SN/A
1382623SN/A    void translationFault(const Fault &fault);
1392623SN/A
1402623SN/A    PacketPtr buildPacket(RequestPtr req, bool read);
1412948Ssaidi@eecs.umich.edu    void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
1422948Ssaidi@eecs.umich.edu            RequestPtr req1, RequestPtr req2, RequestPtr req,
1432623SN/A            uint8_t *data, bool read);
1442623SN/A
1454192Sktlim@umich.edu    bool handleReadPacket(PacketPtr pkt);
1464192Sktlim@umich.edu    // This function always implicitly uses dcache_pkt.
1472623SN/A    bool handleWritePacket();
1482623SN/A
1493349Sbinkertn@umich.edu    /**
1502623SN/A     * A TimingCPUPort overrides the default behaviour of the
1512657Ssaidi@eecs.umich.edu     * recvTiming and recvRetry and implements events for the
1522948Ssaidi@eecs.umich.edu     * scheduling of handling of incoming packets in the following
1532948Ssaidi@eecs.umich.edu     * cycle.
1542948Ssaidi@eecs.umich.edu     */
1552948Ssaidi@eecs.umich.edu    class TimingCPUPort : public MasterPort
1562948Ssaidi@eecs.umich.edu    {
1572948Ssaidi@eecs.umich.edu      public:
1584873Sstever@eecs.umich.edu
1592948Ssaidi@eecs.umich.edu        TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
1602948Ssaidi@eecs.umich.edu            : MasterPort(_name, _cpu), cpu(_cpu), retryRespEvent(this)
1612948Ssaidi@eecs.umich.edu        { }
1622948Ssaidi@eecs.umich.edu
1632623SN/A      protected:
1642623SN/A
1652623SN/A        /**
1662623SN/A         * Snooping a coherence request, do nothing.
1672623SN/A         */
1683349Sbinkertn@umich.edu        virtual void recvTimingSnoopReq(PacketPtr pkt) {}
1693349Sbinkertn@umich.edu
1702623SN/A        TimingSimpleCPU* cpu;
1713222Sktlim@umich.edu
1723170Sstever@eecs.umich.edu        struct TickEvent : public Event
1732623SN/A        {
1742623SN/A            PacketPtr pkt;
1752856Srdreslin@umich.edu            TimingSimpleCPU *cpu;
1762856Srdreslin@umich.edu
1772623SN/A            TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
1782623SN/A            const char *description() const { return "Timing CPU tick"; }
1792623SN/A            void schedule(PacketPtr _pkt, Tick t);
1802901Ssaidi@eecs.umich.edu        };
1812798Sktlim@umich.edu
1822798Sktlim@umich.edu        EventWrapper<MasterPort, &MasterPort::sendRetryResp> retryRespEvent;
1832798Sktlim@umich.edu    };
1842623SN/A
1852623SN/A    class IcachePort : public TimingCPUPort
1862623SN/A    {
1872623SN/A      public:
1882623SN/A
1892623SN/A        IcachePort(TimingSimpleCPU *_cpu)
1902623SN/A            : TimingCPUPort(_cpu->name() + ".icache_port", _cpu),
1912623SN/A              tickEvent(_cpu)
1925177Sgblack@eecs.umich.edu        { }
1935177Sgblack@eecs.umich.edu
1945177Sgblack@eecs.umich.edu      protected:
1952623SN/A
1962623SN/A        virtual bool recvTimingResp(PacketPtr pkt);
1972623SN/A
1985177Sgblack@eecs.umich.edu        virtual void recvReqRetry();
1995177Sgblack@eecs.umich.edu
2005177Sgblack@eecs.umich.edu        struct ITickEvent : public TickEvent
2012623SN/A        {
2023349Sbinkertn@umich.edu
2033349Sbinkertn@umich.edu            ITickEvent(TimingSimpleCPU *_cpu)
2042644Sstever@eecs.umich.edu                : TickEvent(_cpu) {}
2054471Sstever@eecs.umich.edu            void process();
2065315Sstever@gmail.com            const char *description() const { return "Timing CPU icache tick"; }
2075315Sstever@gmail.com        };
2085315Sstever@gmail.com
2095315Sstever@gmail.com        ITickEvent tickEvent;
2105315Sstever@gmail.com
2115315Sstever@gmail.com    };
2122798Sktlim@umich.edu
2134471Sstever@eecs.umich.edu    class DcachePort : public TimingCPUPort
2144471Sstever@eecs.umich.edu    {
2154471Sstever@eecs.umich.edu      public:
2164471Sstever@eecs.umich.edu
2175103Ssaidi@eecs.umich.edu        DcachePort(TimingSimpleCPU *_cpu)
2185103Ssaidi@eecs.umich.edu            : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu),
2195103Ssaidi@eecs.umich.edu              tickEvent(_cpu)
2205103Ssaidi@eecs.umich.edu        {
2215103Ssaidi@eecs.umich.edu           cacheBlockMask = ~(cpu->cacheLineSize() - 1);
2225103Ssaidi@eecs.umich.edu        }
2235103Ssaidi@eecs.umich.edu
2245103Ssaidi@eecs.umich.edu        Addr cacheBlockMask;
2252839Sktlim@umich.edu      protected:
2262623SN/A
2272623SN/A        /** Snoop a coherence request, we need to check if this causes
2282623SN/A         * a wakeup event on a cpu that is monitoring an address
229         */
230        virtual void recvTimingSnoopReq(PacketPtr pkt);
231        virtual void recvFunctionalSnoop(PacketPtr pkt);
232
233        virtual bool recvTimingResp(PacketPtr pkt);
234
235        virtual void recvReqRetry();
236
237        virtual bool isSnooping() const {
238            return true;
239        }
240
241        struct DTickEvent : public TickEvent
242        {
243            DTickEvent(TimingSimpleCPU *_cpu)
244                : TickEvent(_cpu) {}
245            void process();
246            const char *description() const { return "Timing CPU dcache tick"; }
247        };
248
249        DTickEvent tickEvent;
250
251    };
252
253    void updateCycleCounts();
254
255    IcachePort icachePort;
256    DcachePort dcachePort;
257
258    PacketPtr ifetch_pkt;
259    PacketPtr dcache_pkt;
260
261    Cycles previousCycle;
262
263  protected:
264
265     /** Return a reference to the data port. */
266    virtual MasterPort &getDataPort() { return dcachePort; }
267
268    /** Return a reference to the instruction port. */
269    virtual MasterPort &getInstPort() { return icachePort; }
270
271  public:
272
273    unsigned int drain(DrainManager *drain_manager);
274    void drainResume();
275
276    void switchOut();
277    void takeOverFrom(BaseCPU *oldCPU);
278
279    void verifyMemoryMode() const;
280
281    virtual void activateContext(ThreadID thread_num);
282    virtual void suspendContext(ThreadID thread_num);
283
284    Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
285
286    Fault writeMem(uint8_t *data, unsigned size,
287                   Addr addr, unsigned flags, uint64_t *res);
288
289    void fetch();
290    void sendFetch(const Fault &fault, RequestPtr req, ThreadContext *tc);
291    void completeIfetch(PacketPtr );
292    void completeDataAccess(PacketPtr pkt);
293    void advanceInst(const Fault &fault);
294
295    /** This function is used by the page table walker to determine if it could
296     * translate the a pending request or if the underlying request has been
297     * squashed. This always returns false for the simple timing CPU as it never
298     * executes any instructions speculatively.
299     * @ return Is the current instruction squashed?
300     */
301    bool isSquashed() const { return false; }
302
303    /**
304     * Print state of address in memory system via PrintReq (for
305     * debugging).
306     */
307    void printAddr(Addr a);
308
309    /**
310     * Finish a DTB translation.
311     * @param state The DTB translation state.
312     */
313    void finishTranslation(WholeTranslationState *state);
314
315  private:
316
317    typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent;
318    FetchEvent fetchEvent;
319
320    struct IprEvent : Event {
321        Packet *pkt;
322        TimingSimpleCPU *cpu;
323        IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t);
324        virtual void process();
325        virtual const char *description() const;
326    };
327
328    /**
329     * Check if a system is in a drained state.
330     *
331     * We need to drain if:
332     * <ul>
333     * <li>We are in the middle of a microcode sequence as some CPUs
334     *     (e.g., HW accelerated CPUs) can't be started in the middle
335     *     of a gem5 microcode sequence.
336     *
337     * <li>Stay at PC is true.
338     *
339     * <li>A fetch event is scheduled. Normally this would never be the
340     *     case with microPC() == 0, but right after a context is
341     *     activated it can happen.
342     * </ul>
343     */
344    bool isDrained() {
345        return microPC() == 0 && !stayAtPC && !fetchEvent.scheduled();
346    }
347
348    /**
349     * Try to complete a drain request.
350     *
351     * @returns true if the CPU is drained, false otherwise.
352     */
353    bool tryCompleteDrain();
354
355    /**
356     * Drain manager to use when signaling drain completion
357     *
358     * This pointer is non-NULL when draining and NULL otherwise.
359     */
360    DrainManager *drainManager;
361};
362
363#endif // __CPU_SIMPLE_TIMING_HH__
364