timing.hh revision 10529
12SN/A/*
21762SN/A * Copyright (c) 2012-2013 ARM Limited
32SN/A * All rights reserved
42SN/A *
52SN/A * The license below extends only to copyright in the software and shall
62SN/A * not be construed as granting a license to any other intellectual
72SN/A * property including but not limited to intellectual property relating
82SN/A * to a hardware implementation of the functionality of the software
92SN/A * licensed hereunder.  You may use the software subject to the license
102SN/A * terms below provided that you ensure that this notice is replicated
112SN/A * unmodified and in its entirety in all distributions of the software,
122SN/A * modified or unmodified, in source code or in binary form.
132SN/A *
142SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
152SN/A * All rights reserved.
162SN/A *
172SN/A * Redistribution and use in source and binary forms, with or without
182SN/A * modification, are permitted provided that the following conditions are
192SN/A * met: redistributions of source code must retain the above copyright
202SN/A * notice, this list of conditions and the following disclaimer;
212SN/A * redistributions in binary form must reproduce the above copyright
222SN/A * notice, this list of conditions and the following disclaimer in the
232SN/A * documentation and/or other materials provided with the distribution;
242SN/A * neither the name of the copyright holders nor the names of its
252SN/A * contributors may be used to endorse or promote products derived from
262SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282760Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292760Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392SN/A *
402SN/A * Authors: Steve Reinhardt
418229Snate@binkert.org */
422SN/A
438229Snate@binkert.org#ifndef __CPU_SIMPLE_TIMING_HH__
444841Ssaidi@eecs.umich.edu#define __CPU_SIMPLE_TIMING_HH__
452SN/A
466214Snate@binkert.org#include "cpu/simple/base.hh"
472SN/A#include "cpu/translation.hh"
482738Sstever@eecs.umich.edu#include "params/TimingSimpleCPU.hh"
49395SN/A
50237SN/Aclass TimingSimpleCPU : public BaseSimpleCPU
514000Ssaidi@eecs.umich.edu{
522SN/A  public:
539048SAli.Saidi@ARM.com
549048SAli.Saidi@ARM.com    TimingSimpleCPU(TimingSimpleCPUParams * params);
559056SAli.Saidi@ARM.com    virtual ~TimingSimpleCPU();
569048SAli.Saidi@ARM.com
579048SAli.Saidi@ARM.com    virtual void init();
589056SAli.Saidi@ARM.com
599048SAli.Saidi@ARM.com  private:
609048SAli.Saidi@ARM.com
619048SAli.Saidi@ARM.com    /*
62217SN/A     * If an access needs to be broken into fragments, currently at most two,
63502SN/A     * the the following two classes are used as the sender state of the
64217SN/A     * packets so the CPU can keep track of everything. In the main packet
65217SN/A     * sender state, there's an array with a spot for each fragment. If a
66237SN/A     * fragment has already been accepted by the CPU, aka isn't waiting for
67502SN/A     * a retry, it's pointer is NULL. After each fragment has successfully
68217SN/A     * been processed, the "outstanding" counter is decremented. Once the
69217SN/A     * count is zero, the entire larger access is complete.
706820SLisa.Hsu@amd.com     */
716820SLisa.Hsu@amd.com    class SplitMainSenderState : public Packet::SenderState
726820SLisa.Hsu@amd.com    {
736820SLisa.Hsu@amd.com      public:
74217SN/A        int outstanding;
756227Snate@binkert.org        PacketPtr fragments[2];
76217SN/A
77217SN/A        int
784841Ssaidi@eecs.umich.edu        getPendingFragment()
794841Ssaidi@eecs.umich.edu        {
804841Ssaidi@eecs.umich.edu            if (fragments[0]) {
814841Ssaidi@eecs.umich.edu                return 0;
827948SAli.Saidi@ARM.com            } else if (fragments[1]) {
837948SAli.Saidi@ARM.com                return 1;
847948SAli.Saidi@ARM.com            } else {
857948SAli.Saidi@ARM.com                return -1;
86237SN/A            }
876227Snate@binkert.org        }
88217SN/A    };
894841Ssaidi@eecs.umich.edu
904841Ssaidi@eecs.umich.edu    class SplitFragmentSenderState : public Packet::SenderState
914841Ssaidi@eecs.umich.edu    {
924841Ssaidi@eecs.umich.edu      public:
937948SAli.Saidi@ARM.com        SplitFragmentSenderState(PacketPtr _bigPkt, int _index) :
947948SAli.Saidi@ARM.com            bigPkt(_bigPkt), index(_index)
957948SAli.Saidi@ARM.com        {}
967948SAli.Saidi@ARM.com        PacketPtr bigPkt;
97237SN/A        int index;
98237SN/A
994000Ssaidi@eecs.umich.edu        void
100237SN/A        clearFromParent()
1018902Sandreas.hansson@arm.com        {
1028902Sandreas.hansson@arm.com            SplitMainSenderState * main_send_state =
1038902Sandreas.hansson@arm.com                dynamic_cast<SplitMainSenderState *>(bigPkt->senderState);
1048902Sandreas.hansson@arm.com            main_send_state->fragments[index] = NULL;
1058902Sandreas.hansson@arm.com        }
1068902Sandreas.hansson@arm.com    };
1078902Sandreas.hansson@arm.com
1088902Sandreas.hansson@arm.com    class FetchTranslation : public BaseTLB::Translation
1098902Sandreas.hansson@arm.com    {
1108902Sandreas.hansson@arm.com      protected:
1118902Sandreas.hansson@arm.com        TimingSimpleCPU *cpu;
112237SN/A
113217SN/A      public:
114217SN/A        FetchTranslation(TimingSimpleCPU *_cpu)
115217SN/A            : cpu(_cpu)
116237SN/A        {}
1175543Ssaidi@eecs.umich.edu
118217SN/A        void
1195543Ssaidi@eecs.umich.edu        markDelayed()
1206820SLisa.Hsu@amd.com        {
121217SN/A            assert(cpu->_status == BaseSimpleCPU::Running);
122223SN/A            cpu->_status = ITBWaitResponse;
1235543Ssaidi@eecs.umich.edu        }
124223SN/A
1255543Ssaidi@eecs.umich.edu        void
1265543Ssaidi@eecs.umich.edu        finish(const Fault &fault, RequestPtr req, ThreadContext *tc,
1275543Ssaidi@eecs.umich.edu               BaseTLB::Mode mode)
1285543Ssaidi@eecs.umich.edu        {
1298902Sandreas.hansson@arm.com            cpu->sendFetch(fault, req, tc);
130223SN/A        }
131223SN/A    };
1325543Ssaidi@eecs.umich.edu    FetchTranslation fetchTranslation;
133217SN/A
134217SN/A    void sendData(RequestPtr req, uint8_t *data, uint64_t *res, bool read);
1355543Ssaidi@eecs.umich.edu    void sendSplitData(RequestPtr req1, RequestPtr req2, RequestPtr req,
136237SN/A                       uint8_t *data, bool read);
137237SN/A
1385543Ssaidi@eecs.umich.edu    void translationFault(const Fault &fault);
139237SN/A
1405543Ssaidi@eecs.umich.edu    void buildPacket(PacketPtr &pkt, RequestPtr req, bool read);
1415543Ssaidi@eecs.umich.edu    void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
1425543Ssaidi@eecs.umich.edu            RequestPtr req1, RequestPtr req2, RequestPtr req,
1435543Ssaidi@eecs.umich.edu            uint8_t *data, bool read);
1448902Sandreas.hansson@arm.com
145237SN/A    bool handleReadPacket(PacketPtr pkt);
146217SN/A    // This function always implicitly uses dcache_pkt.
1472SN/A    bool handleWritePacket();
1482SN/A
1492SN/A    /**
150395SN/A     * A TimingCPUPort overrides the default behaviour of the
1512SN/A     * recvTiming and recvRetry and implements events for the
1522SN/A     * scheduling of handling of incoming packets in the following
153510SN/A     * cycle.
154510SN/A     */
1552SN/A    class TimingCPUPort : public MasterPort
1562SN/A    {
1575739Snate@binkert.org      public:
1585739Snate@binkert.org
1592SN/A        TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
160265SN/A            : MasterPort(_name, _cpu), cpu(_cpu), retryEvent(this)
161512SN/A        { }
1622SN/A
1635739Snate@binkert.org      protected:
1645739Snate@binkert.org
165237SN/A        /**
1665739Snate@binkert.org         * Snooping a coherence request, do nothing.
1672SN/A         */
1682287SN/A        virtual void recvTimingSnoopReq(PacketPtr pkt) {}
1692287SN/A
1702287SN/A        TimingSimpleCPU* cpu;
1712868Sktlim@umich.edu
172395SN/A        struct TickEvent : public Event
1732SN/A        {
1742SN/A            PacketPtr pkt;
1752SN/A            TimingSimpleCPU *cpu;
176395SN/A
177395SN/A            TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
1782SN/A            const char *description() const { return "Timing CPU tick"; }
1792SN/A            void schedule(PacketPtr _pkt, Tick t);
1802SN/A        };
181395SN/A
1822SN/A        EventWrapper<MasterPort, &MasterPort::sendRetry> retryEvent;
183395SN/A    };
1842SN/A
1852SN/A    class IcachePort : public TimingCPUPort
186395SN/A    {
1872SN/A      public:
188395SN/A
1892SN/A        IcachePort(TimingSimpleCPU *_cpu)
1902SN/A            : TimingCPUPort(_cpu->name() + ".icache_port", _cpu),
1912SN/A              tickEvent(_cpu)
192395SN/A        { }
1932SN/A
194395SN/A      protected:
1952SN/A
196395SN/A        virtual bool recvTimingResp(PacketPtr pkt);
1972SN/A
1982SN/A        virtual void recvRetry();
199395SN/A
200395SN/A        struct ITickEvent : public TickEvent
2012SN/A        {
2022SN/A
2032SN/A            ITickEvent(TimingSimpleCPU *_cpu)
204395SN/A                : TickEvent(_cpu) {}
205395SN/A            void process();
2062SN/A            const char *description() const { return "Timing CPU icache tick"; }
2072SN/A        };
2082SN/A
2092SN/A        ITickEvent tickEvent;
2102SN/A
2112SN/A    };
212395SN/A
2132SN/A    class DcachePort : public TimingCPUPort
2142SN/A    {
2152SN/A      public:
2162SN/A
2172SN/A        DcachePort(TimingSimpleCPU *_cpu)
2182SN/A            : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu),
2192SN/A              tickEvent(_cpu)
2202SN/A        {
221395SN/A           cacheBlockMask = ~(cpu->cacheLineSize() - 1);
222395SN/A        }
2232738Sstever@eecs.umich.edu
2242SN/A        Addr cacheBlockMask;
2252SN/A      protected:
2262SN/A
2272SN/A        /** Snoop a coherence request, we need to check if this causes
2282SN/A         * a wakeup event on a cpu that is monitoring an address
229395SN/A         */
230395SN/A        virtual void recvTimingSnoopReq(PacketPtr pkt);
2312SN/A        virtual void recvFunctionalSnoop(PacketPtr pkt);
232395SN/A
2332SN/A        virtual bool recvTimingResp(PacketPtr pkt);
234395SN/A
2352SN/A        virtual void recvRetry();
236395SN/A
2372738Sstever@eecs.umich.edu        virtual bool isSnooping() const {
2382SN/A            return true;
2392SN/A        }
2402SN/A
2412SN/A        struct DTickEvent : public TickEvent
242395SN/A        {
2432SN/A            DTickEvent(TimingSimpleCPU *_cpu)
2442SN/A                : TickEvent(_cpu) {}
2455543Ssaidi@eecs.umich.edu            void process();
2465543Ssaidi@eecs.umich.edu            const char *description() const { return "Timing CPU dcache tick"; }
247237SN/A        };
2482SN/A
249237SN/A        DTickEvent tickEvent;
250237SN/A
251237SN/A    };
252237SN/A
253237SN/A    void updateCycleCounts();
254237SN/A
255237SN/A    IcachePort icachePort;
2567491Ssteve.reinhardt@amd.com    DcachePort dcachePort;
2579086Sandreas.hansson@arm.com
258237SN/A    PacketPtr ifetch_pkt;
259937SN/A    PacketPtr dcache_pkt;
260937SN/A
261237SN/A    Cycles previousCycle;
262237SN/A
263237SN/A  protected:
264237SN/A
2654000Ssaidi@eecs.umich.edu     /** Return a reference to the data port. */
266304SN/A    virtual MasterPort &getDataPort() { return dcachePort; }
267304SN/A
268449SN/A    /** Return a reference to the instruction port. */
269449SN/A    virtual MasterPort &getInstPort() { return icachePort; }
270449SN/A
2717491Ssteve.reinhardt@amd.com  public:
2727491Ssteve.reinhardt@amd.com
2737491Ssteve.reinhardt@amd.com    unsigned int drain(DrainManager *drain_manager);
2747491Ssteve.reinhardt@amd.com    void drainResume();
2757491Ssteve.reinhardt@amd.com
2767491Ssteve.reinhardt@amd.com    void switchOut();
2777491Ssteve.reinhardt@amd.com    void takeOverFrom(BaseCPU *oldCPU);
2787491Ssteve.reinhardt@amd.com
2797491Ssteve.reinhardt@amd.com    void verifyMemoryMode() const;
2807491Ssteve.reinhardt@amd.com
2817491Ssteve.reinhardt@amd.com    virtual void activateContext(ThreadID thread_num);
2827823Ssteve.reinhardt@amd.com    virtual void suspendContext(ThreadID thread_num);
2837491Ssteve.reinhardt@amd.com
2847491Ssteve.reinhardt@amd.com    Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags);
285449SN/A
286449SN/A    Fault writeMem(uint8_t *data, unsigned size,
287449SN/A                   Addr addr, unsigned flags, uint64_t *res);
288449SN/A
289449SN/A    void fetch();
290449SN/A    void sendFetch(const Fault &fault, RequestPtr req, ThreadContext *tc);
291449SN/A    void completeIfetch(PacketPtr );
292449SN/A    void completeDataAccess(PacketPtr pkt);
293449SN/A    void advanceInst(const Fault &fault);
294237SN/A
2952SN/A    /** This function is used by the page table walker to determine if it could
2962SN/A     * 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