decode.hh revision 2307
112726Snikos.nikoleris@arm.com/*
29380SAndreas.Sandberg@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
39380SAndreas.Sandberg@ARM.com * All rights reserved.
49380SAndreas.Sandberg@ARM.com *
59380SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
69380SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
79380SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
89380SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
99380SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
109380SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
119380SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
129380SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
139380SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
149380SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
159380SAndreas.Sandberg@ARM.com *
169380SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179380SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189380SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199380SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209380SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219380SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229380SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239380SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249380SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259380SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269380SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279380SAndreas.Sandberg@ARM.com */
289380SAndreas.Sandberg@ARM.com
299380SAndreas.Sandberg@ARM.com#ifndef __CPU_O3_DECODE_HH__
309380SAndreas.Sandberg@ARM.com#define __CPU_O3_DECODE_HH__
319380SAndreas.Sandberg@ARM.com
329380SAndreas.Sandberg@ARM.com#include <queue>
339380SAndreas.Sandberg@ARM.com
349380SAndreas.Sandberg@ARM.com#include "base/statistics.hh"
359380SAndreas.Sandberg@ARM.com#include "base/timebuf.hh"
369380SAndreas.Sandberg@ARM.com
379792Sandreas.hansson@arm.com/**
389380SAndreas.Sandberg@ARM.com * DefaultDecode class handles both single threaded and SMT decode. Its width is
399380SAndreas.Sandberg@ARM.com * specified by the parameters; each cycles it tries to decode that many
4012070Snikos.nikoleris@arm.com * instructions. Because instructions are actually decoded when the StaticInst
419380SAndreas.Sandberg@ARM.com * is created, this stage does not do much other than check any PC-relative
429380SAndreas.Sandberg@ARM.com * branches.
439380SAndreas.Sandberg@ARM.com */
4411682Sandreas.hansson@arm.comtemplate<class Impl>
4511682Sandreas.hansson@arm.comclass DefaultDecode
4612070Snikos.nikoleris@arm.com{
4711682Sandreas.hansson@arm.com  private:
4812070Snikos.nikoleris@arm.com    // Typedefs from the Impl.
499380SAndreas.Sandberg@ARM.com    typedef typename Impl::FullCPU FullCPU;
509654SAndreas.Sandberg@ARM.com    typedef typename Impl::DynInstPtr DynInstPtr;
519654SAndreas.Sandberg@ARM.com    typedef typename Impl::Params Params;
529380SAndreas.Sandberg@ARM.com    typedef typename Impl::CPUPol CPUPol;
539380SAndreas.Sandberg@ARM.com
549380SAndreas.Sandberg@ARM.com    // Typedefs from the CPU policy.
559380SAndreas.Sandberg@ARM.com    typedef typename CPUPol::FetchStruct FetchStruct;
569380SAndreas.Sandberg@ARM.com    typedef typename CPUPol::DecodeStruct DecodeStruct;
579380SAndreas.Sandberg@ARM.com    typedef typename CPUPol::TimeStruct TimeStruct;
589380SAndreas.Sandberg@ARM.com
599380SAndreas.Sandberg@ARM.com  public:
609380SAndreas.Sandberg@ARM.com    /** Overall decode stage status. Used to determine if the CPU can
619380SAndreas.Sandberg@ARM.com     * deschedule itself due to a lack of activity.
629380SAndreas.Sandberg@ARM.com     */
639792Sandreas.hansson@arm.com    enum DecodeStatus {
6411156Sandreas.sandberg@arm.com        Active,
6512070Snikos.nikoleris@arm.com        Inactive
669792Sandreas.hansson@arm.com    };
679380SAndreas.Sandberg@ARM.com
689380SAndreas.Sandberg@ARM.com    /** Individual thread status. */
699380SAndreas.Sandberg@ARM.com    enum ThreadStatus {
709792Sandreas.hansson@arm.com        Running,
719380SAndreas.Sandberg@ARM.com        Idle,
729380SAndreas.Sandberg@ARM.com        StartSquash,
739380SAndreas.Sandberg@ARM.com        Squashing,
7410512SAli.Saidi@ARM.com        Blocked,
7512070Snikos.nikoleris@arm.com        Unblocking
769380SAndreas.Sandberg@ARM.com    };
779380SAndreas.Sandberg@ARM.com
789792Sandreas.hansson@arm.com  private:
799380SAndreas.Sandberg@ARM.com    /** Decode status. */
809380SAndreas.Sandberg@ARM.com    DecodeStatus _status;
8111156Sandreas.sandberg@arm.com
829380SAndreas.Sandberg@ARM.com    /** Per-thread status. */
8312070Snikos.nikoleris@arm.com    ThreadStatus decodeStatus[Impl::MaxThreads];
849380SAndreas.Sandberg@ARM.com
859793Sakash.bagdia@arm.com  public:
869380SAndreas.Sandberg@ARM.com    /** DefaultDecode constructor. */
8711156Sandreas.sandberg@arm.com    DefaultDecode(Params *params);
8811156Sandreas.sandberg@arm.com
899793Sakash.bagdia@arm.com    /** Returns the name of decode. */
909380SAndreas.Sandberg@ARM.com    std::string name() const;
919380SAndreas.Sandberg@ARM.com
929380SAndreas.Sandberg@ARM.com    /** Registers statistics. */
939380SAndreas.Sandberg@ARM.com    void regStats();
949380SAndreas.Sandberg@ARM.com
959380SAndreas.Sandberg@ARM.com    /** Sets CPU pointer. */
969380SAndreas.Sandberg@ARM.com    void setCPU(FullCPU *cpu_ptr);
979380SAndreas.Sandberg@ARM.com
989380SAndreas.Sandberg@ARM.com    /** Sets the main backwards communication time buffer pointer. */
999380SAndreas.Sandberg@ARM.com    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
1009380SAndreas.Sandberg@ARM.com
1019380SAndreas.Sandberg@ARM.com    /** Sets pointer to time buffer used to communicate to the next stage. */
10210884Sandreas.hansson@arm.com    void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr);
10310884Sandreas.hansson@arm.com
1049380SAndreas.Sandberg@ARM.com    /** Sets pointer to time buffer coming from fetch. */
1059380SAndreas.Sandberg@ARM.com    void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
1069380SAndreas.Sandberg@ARM.com
1079380SAndreas.Sandberg@ARM.com    /** Sets pointer to list of active threads. */
1089380SAndreas.Sandberg@ARM.com    void setActiveThreads(std::list<unsigned> *at_ptr);
1099380SAndreas.Sandberg@ARM.com
1109380SAndreas.Sandberg@ARM.com    void switchOut();
1119380SAndreas.Sandberg@ARM.com
1129380SAndreas.Sandberg@ARM.com    void takeOverFrom();
1139380SAndreas.Sandberg@ARM.com    /** Ticks decode, processing all input signals and decoding as many
11410720Sandreas.hansson@arm.com     * instructions as possible.
1159793Sakash.bagdia@arm.com     */
1169793Sakash.bagdia@arm.com    void tick();
1179380SAndreas.Sandberg@ARM.com
1189380SAndreas.Sandberg@ARM.com    /** Determines what to do based on decode's current status.
1199380SAndreas.Sandberg@ARM.com     * @param status_change decode() sets this variable if there was a status
1209380SAndreas.Sandberg@ARM.com     * change (ie switching from from blocking to unblocking).
1219674Snilay@cs.wisc.edu     * @param tid Thread id to decode instructions from.
1229380SAndreas.Sandberg@ARM.com     */
1239380SAndreas.Sandberg@ARM.com    void decode(bool &status_change, unsigned tid);
1249380SAndreas.Sandberg@ARM.com
1259380SAndreas.Sandberg@ARM.com    /** Processes instructions from fetch and passes them on to rename.
1269380SAndreas.Sandberg@ARM.com     * Decoding of instructions actually happens when they are created in
1279380SAndreas.Sandberg@ARM.com     * fetch, so this function mostly checks if PC-relative branches are
1289674Snilay@cs.wisc.edu     * correct.
1299674Snilay@cs.wisc.edu     */
1309674Snilay@cs.wisc.edu    void decodeInsts(unsigned tid);
1319674Snilay@cs.wisc.edu
1329674Snilay@cs.wisc.edu  private:
1339380SAndreas.Sandberg@ARM.com    /** Inserts a thread's instructions into the skid buffer, to be decoded
1349654SAndreas.Sandberg@ARM.com     * once decode unblocks.
1359654SAndreas.Sandberg@ARM.com     */
1369654SAndreas.Sandberg@ARM.com    void skidInsert(unsigned tid);
1379654SAndreas.Sandberg@ARM.com
1389654SAndreas.Sandberg@ARM.com    /** Returns if all of the skid buffers are empty. */
1399654SAndreas.Sandberg@ARM.com    bool skidsEmpty();
1409654SAndreas.Sandberg@ARM.com
1419654SAndreas.Sandberg@ARM.com    /** Updates overall decode status based on all of the threads' statuses. */
1429380SAndreas.Sandberg@ARM.com    void updateStatus();
1439380SAndreas.Sandberg@ARM.com
1449380SAndreas.Sandberg@ARM.com    /** Separates instructions from fetch into individual lists of instructions
1459380SAndreas.Sandberg@ARM.com     * sorted by thread.
1469380SAndreas.Sandberg@ARM.com     */
1479380SAndreas.Sandberg@ARM.com    void sortInsts();
1489793Sakash.bagdia@arm.com
1499793Sakash.bagdia@arm.com    /** Reads all stall signals from the backwards communication timebuffer. */
1509380SAndreas.Sandberg@ARM.com    void readStallSignals(unsigned tid);
1519654SAndreas.Sandberg@ARM.com
1529654SAndreas.Sandberg@ARM.com    /** Checks all input signals and updates decode's status appropriately. */
1539654SAndreas.Sandberg@ARM.com    bool checkSignalsAndUpdate(unsigned tid);
1549654SAndreas.Sandberg@ARM.com
15512070Snikos.nikoleris@arm.com    /** Checks all stall signals, and returns if any are true. */
15612070Snikos.nikoleris@arm.com    bool checkStall(unsigned tid) const;
15712070Snikos.nikoleris@arm.com
15812070Snikos.nikoleris@arm.com    /** Returns if there any instructions from fetch on this cycle. */
15912070Snikos.nikoleris@arm.com    inline bool fetchInstsValid();
16012070Snikos.nikoleris@arm.com
16111604Sandreas.hansson@arm.com    /** Switches decode to blocking, and signals back that decode has
16212070Snikos.nikoleris@arm.com     * become blocked.
16312070Snikos.nikoleris@arm.com     * @return Returns true if there is a status change.
16412070Snikos.nikoleris@arm.com     */
16512070Snikos.nikoleris@arm.com    bool block(unsigned tid);
16612070Snikos.nikoleris@arm.com
16712070Snikos.nikoleris@arm.com    /** Switches decode to unblocking if the skid buffer is empty, and
16812070Snikos.nikoleris@arm.com     * signals back that decode has unblocked.
16912070Snikos.nikoleris@arm.com     * @return Returns true if there is a status change.
17012070Snikos.nikoleris@arm.com     */
17112070Snikos.nikoleris@arm.com    bool unblock(unsigned tid);
17212070Snikos.nikoleris@arm.com
17312598Snikos.nikoleris@arm.com    /** Squashes if there is a PC-relative branch that was predicted
17412070Snikos.nikoleris@arm.com     * incorrectly. Sends squash information back to fetch.
17512598Snikos.nikoleris@arm.com     */
17612070Snikos.nikoleris@arm.com    void squash(DynInstPtr &inst, unsigned tid);
17712070Snikos.nikoleris@arm.com
17812070Snikos.nikoleris@arm.com  public:
17912070Snikos.nikoleris@arm.com    /** Squashes due to commit signalling a squash. Changes status to
18012070Snikos.nikoleris@arm.com     * squashing and clears block/unblock signals as needed.
18112070Snikos.nikoleris@arm.com     */
18212070Snikos.nikoleris@arm.com    unsigned squash(unsigned tid);
18312070Snikos.nikoleris@arm.com
18412070Snikos.nikoleris@arm.com  private:
18512070Snikos.nikoleris@arm.com    // Interfaces to objects outside of decode.
18612070Snikos.nikoleris@arm.com    /** CPU interface. */
18712070Snikos.nikoleris@arm.com    FullCPU *cpu;
18812070Snikos.nikoleris@arm.com
18912070Snikos.nikoleris@arm.com    /** Time buffer interface. */
1909380SAndreas.Sandberg@ARM.com    TimeBuffer<TimeStruct> *timeBuffer;
1919793Sakash.bagdia@arm.com
1929793Sakash.bagdia@arm.com    /** Wire to get rename's output from backwards time buffer. */
1939793Sakash.bagdia@arm.com    typename TimeBuffer<TimeStruct>::wire fromRename;
1949793Sakash.bagdia@arm.com
1959827Sakash.bagdia@arm.com    /** Wire to get iew's information from backwards time buffer. */
1969827Sakash.bagdia@arm.com    typename TimeBuffer<TimeStruct>::wire fromIEW;
1979827Sakash.bagdia@arm.com
1989827Sakash.bagdia@arm.com    /** Wire to get commit's information from backwards time buffer. */
1999793Sakash.bagdia@arm.com    typename TimeBuffer<TimeStruct>::wire fromCommit;
2009793Sakash.bagdia@arm.com
2019793Sakash.bagdia@arm.com    /** Wire to write information heading to previous stages. */
2029827Sakash.bagdia@arm.com    // Might not be the best name as not only fetch will read it.
2039827Sakash.bagdia@arm.com    typename TimeBuffer<TimeStruct>::wire toFetch;
2049827Sakash.bagdia@arm.com
2059793Sakash.bagdia@arm.com    /** Decode instruction queue. */
2069380SAndreas.Sandberg@ARM.com    TimeBuffer<DecodeStruct> *decodeQueue;
2079380SAndreas.Sandberg@ARM.com
2089380SAndreas.Sandberg@ARM.com    /** Wire used to write any information heading to rename. */
2099380SAndreas.Sandberg@ARM.com    typename TimeBuffer<DecodeStruct>::wire toRename;
2109380SAndreas.Sandberg@ARM.com
2119380SAndreas.Sandberg@ARM.com    /** Fetch instruction queue interface. */
2129380SAndreas.Sandberg@ARM.com    TimeBuffer<FetchStruct> *fetchQueue;
2139380SAndreas.Sandberg@ARM.com
2149380SAndreas.Sandberg@ARM.com    /** Wire to get fetch's output from fetch queue. */
2159380SAndreas.Sandberg@ARM.com    typename TimeBuffer<FetchStruct>::wire fromFetch;
2169380SAndreas.Sandberg@ARM.com
2179792Sandreas.hansson@arm.com    /** Queue of all instructions coming from fetch this cycle. */
2189792Sandreas.hansson@arm.com    std::queue<DynInstPtr> insts[Impl::MaxThreads];
2199792Sandreas.hansson@arm.com
2209792Sandreas.hansson@arm.com    /** Skid buffer between fetch and decode. */
2219792Sandreas.hansson@arm.com    std::queue<DynInstPtr> skidBuffer[Impl::MaxThreads];
2229792Sandreas.hansson@arm.com
2239792Sandreas.hansson@arm.com    /** Variable that tracks if decode has written to the time buffer this
2249792Sandreas.hansson@arm.com     * cycle. Used to tell CPU if there is activity this cycle.
2259792Sandreas.hansson@arm.com     */
2269792Sandreas.hansson@arm.com    bool wroteToTimeBuffer;
2279792Sandreas.hansson@arm.com
22810720Sandreas.hansson@arm.com    /** Source of possible stalls. */
22911156Sandreas.sandberg@arm.com    struct Stalls {
23011156Sandreas.sandberg@arm.com        bool rename;
23112070Snikos.nikoleris@arm.com        bool iew;
23212070Snikos.nikoleris@arm.com        bool commit;
2339792Sandreas.hansson@arm.com    };
2349792Sandreas.hansson@arm.com
2359792Sandreas.hansson@arm.com    /** Tracks which stages are telling decode to stall. */
2369792Sandreas.hansson@arm.com    Stalls stalls[Impl::MaxThreads];
2379792Sandreas.hansson@arm.com
2389792Sandreas.hansson@arm.com    /** Rename to decode delay, in ticks. */
2399792Sandreas.hansson@arm.com    unsigned renameToDecodeDelay;
2409792Sandreas.hansson@arm.com
2419792Sandreas.hansson@arm.com    /** IEW to decode delay, in ticks. */
2429792Sandreas.hansson@arm.com    unsigned iewToDecodeDelay;
2439792Sandreas.hansson@arm.com
2449792Sandreas.hansson@arm.com    /** Commit to decode delay, in ticks. */
2459792Sandreas.hansson@arm.com    unsigned commitToDecodeDelay;
2469792Sandreas.hansson@arm.com
2479792Sandreas.hansson@arm.com    /** Fetch to decode delay, in ticks. */
2489792Sandreas.hansson@arm.com    unsigned fetchToDecodeDelay;
2499792Sandreas.hansson@arm.com
2509792Sandreas.hansson@arm.com    /** The width of decode, in instructions. */
2519792Sandreas.hansson@arm.com    unsigned decodeWidth;
2529792Sandreas.hansson@arm.com
2539792Sandreas.hansson@arm.com    /** Index of instructions being sent to rename. */
2549792Sandreas.hansson@arm.com    unsigned toRenameIndex;
2559792Sandreas.hansson@arm.com
25610884Sandreas.hansson@arm.com    /** number of Active Threads*/
25710884Sandreas.hansson@arm.com    unsigned numThreads;
2589792Sandreas.hansson@arm.com
2599792Sandreas.hansson@arm.com    /** List of active thread ids */
2609792Sandreas.hansson@arm.com    std::list<unsigned> *activeThreads;
2619792Sandreas.hansson@arm.com
2629792Sandreas.hansson@arm.com    /** Number of branches in flight. */
2639380SAndreas.Sandberg@ARM.com    unsigned branchCount[Impl::MaxThreads];
2649380SAndreas.Sandberg@ARM.com
2659380SAndreas.Sandberg@ARM.com    /** Maximum size of the skid buffer. */
2669380SAndreas.Sandberg@ARM.com    unsigned skidBufferMax;
2679380SAndreas.Sandberg@ARM.com
2689380SAndreas.Sandberg@ARM.com    /** Stat for total number of idle cycles. */
2699380SAndreas.Sandberg@ARM.com    Stats::Scalar<> decodeIdleCycles;
2709380SAndreas.Sandberg@ARM.com    /** Stat for total number of blocked cycles. */
2719380SAndreas.Sandberg@ARM.com    Stats::Scalar<> decodeBlockedCycles;
27212070Snikos.nikoleris@arm.com    /** Stat for total number of normal running cycles. */
27312070Snikos.nikoleris@arm.com    Stats::Scalar<> decodeRunCycles;
27412070Snikos.nikoleris@arm.com    /** Stat for total number of unblocking cycles. */
27512070Snikos.nikoleris@arm.com    Stats::Scalar<> decodeUnblockCycles;
27612070Snikos.nikoleris@arm.com    /** Stat for total number of squashing cycles. */
27712070Snikos.nikoleris@arm.com    Stats::Scalar<> decodeSquashCycles;
27812070Snikos.nikoleris@arm.com    /** Stat for number of times a branch is resolved at decode. */
27912070Snikos.nikoleris@arm.com    Stats::Scalar<> decodeBranchResolved;
28012070Snikos.nikoleris@arm.com    /** Stat for number of times a branch mispredict is detected. */
28112726Snikos.nikoleris@arm.com    Stats::Scalar<> decodeBranchMispred;
28212726Snikos.nikoleris@arm.com    /** Stat for number of times decode detected a non-control instruction
28312726Snikos.nikoleris@arm.com     * incorrectly predicted as a branch.
28412726Snikos.nikoleris@arm.com     */
28512726Snikos.nikoleris@arm.com    Stats::Scalar<> decodeControlMispred;
28612726Snikos.nikoleris@arm.com    /** Stat for total number of decoded instructions. */
28712726Snikos.nikoleris@arm.com    Stats::Scalar<> decodeDecodedInsts;
28812726Snikos.nikoleris@arm.com    /** Stat for total number of squashed instructions. */
28912726Snikos.nikoleris@arm.com    Stats::Scalar<> decodeSquashedInsts;
29012726Snikos.nikoleris@arm.com};
29112070Snikos.nikoleris@arm.com
29212726Snikos.nikoleris@arm.com#endif // __CPU_O3_DECODE_HH__
29312726Snikos.nikoleris@arm.com