lsq.hh revision 7520:67c670459d01
12567SN/A/*
210037SARM gem5 Developers * Copyright (c) 2004-2006 The Regents of The University of Michigan
37585SAli.Saidi@arm.com * All rights reserved.
47585SAli.Saidi@arm.com *
57585SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without
67585SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are
77585SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright
87585SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer;
97585SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright
107585SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the
117585SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution;
127585SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its
137585SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from
142567SN/A * this software without specific prior written permission.
152567SN/A *
162567SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172567SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182567SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192567SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202567SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212567SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222567SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232567SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242567SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252567SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262567SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272567SN/A *
282567SN/A * Authors: Korey Sewell
292567SN/A */
302567SN/A
312567SN/A#ifndef __CPU_O3_LSQ_HH__
322567SN/A#define __CPU_O3_LSQ_HH__
332567SN/A
342567SN/A#include <map>
352567SN/A#include <queue>
362567SN/A
372567SN/A#include "config/full_system.hh"
382567SN/A#include "cpu/inst_seq.hh"
392665SN/A#include "cpu/o3/lsq_unit.hh"
402665SN/A#include "mem/port.hh"
412567SN/A#include "sim/sim_object.hh"
422567SN/A
438229Snate@binkert.orgclass DerivO3CPUParams;
448229Snate@binkert.org
456757SAli.Saidi@ARM.comtemplate <class Impl>
468286SAli.Saidi@ARM.comclass LSQ {
478286SAli.Saidi@ARM.com  public:
488286SAli.Saidi@ARM.com    typedef typename Impl::O3CPU O3CPU;
498286SAli.Saidi@ARM.com    typedef typename Impl::DynInstPtr DynInstPtr;
508706Sandreas.hansson@arm.com    typedef typename Impl::CPUPol::IEW IEW;
5110037SARM gem5 Developers    typedef typename Impl::CPUPol::LSQUnit LSQUnit;
522567SN/A
537650SAli.Saidi@ARM.com    /** SMT policy. */
547650SAli.Saidi@ARM.com    enum LSQPolicy {
552567SN/A        Dynamic,
566757SAli.Saidi@ARM.com        Partitioned,
5710037SARM gem5 Developers        Threshold
5810037SARM gem5 Developers    };
5910037SARM gem5 Developers
6010037SARM gem5 Developers    /** Constructs an LSQ with the given parameters. */
6110537Sandreas.hansson@arm.com    LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params);
6210037SARM gem5 Developers
6310037SARM gem5 Developers    /** Returns the name of the LSQ. */
6410037SARM gem5 Developers    std::string name() const;
6510037SARM gem5 Developers
6610037SARM gem5 Developers    /** Registers statistics of each LSQ unit. */
672567SN/A    void regStats();
6810037SARM gem5 Developers
6910037SARM gem5 Developers    /** Returns dcache port.
7010037SARM gem5 Developers     *  @todo: Dcache port needs to be moved up to this level for SMT
7110037SARM gem5 Developers     *  to work.  For now it just returns the port from one of the
7210037SARM gem5 Developers     *  threads.
7310037SARM gem5 Developers     */
7410037SARM gem5 Developers    Port *getDcachePort() { return &dcachePort; }
7510037SARM gem5 Developers
768885SAli.Saidi@ARM.com    /** Sets the pointer to the list of active threads. */
778885SAli.Saidi@ARM.com    void setActiveThreads(std::list<ThreadID> *at_ptr);
788885SAli.Saidi@ARM.com    /** Switches out the LSQ. */
798885SAli.Saidi@ARM.com    void switchOut();
808885SAli.Saidi@ARM.com    /** Takes over execution from another CPU's thread. */
818885SAli.Saidi@ARM.com    void takeOverFrom();
8210037SARM gem5 Developers
8310037SARM gem5 Developers    /** Number of entries needed for the given amount of threads.*/
8410037SARM gem5 Developers    int entryAmount(ThreadID num_threads);
8510037SARM gem5 Developers    void removeEntries(ThreadID tid);
8610037SARM gem5 Developers    /** Reset the max entries for each thread. */
8710037SARM gem5 Developers    void resetEntries();
8810037SARM gem5 Developers    /** Resize the max entries for a thread. */
8910037SARM gem5 Developers    void resizeEntries(unsigned size, ThreadID tid);
9010037SARM gem5 Developers
9110037SARM gem5 Developers    /** Ticks the LSQ. */
928885SAli.Saidi@ARM.com    void tick();
938885SAli.Saidi@ARM.com    /** Ticks a specific LSQ Unit. */
948885SAli.Saidi@ARM.com    void tick(ThreadID tid)
958885SAli.Saidi@ARM.com    { thread[tid].tick(); }
968706Sandreas.hansson@arm.com
978706Sandreas.hansson@arm.com    /** Inserts a load into the LSQ. */
988706Sandreas.hansson@arm.com    void insertLoad(DynInstPtr &load_inst);
998706Sandreas.hansson@arm.com    /** Inserts a store into the LSQ. */
1008706Sandreas.hansson@arm.com    void insertStore(DynInstPtr &store_inst);
1018706Sandreas.hansson@arm.com
1028706Sandreas.hansson@arm.com    /** Executes a load. */
1038706Sandreas.hansson@arm.com    Fault executeLoad(DynInstPtr &inst);
1048706Sandreas.hansson@arm.com
1058706Sandreas.hansson@arm.com    /** Executes a store. */
1068706Sandreas.hansson@arm.com    Fault executeStore(DynInstPtr &inst);
1078706Sandreas.hansson@arm.com
1082567SN/A    /**
1098885SAli.Saidi@ARM.com     * Commits loads up until the given sequence number for a specific thread.
1108706Sandreas.hansson@arm.com     */
1118286SAli.Saidi@ARM.com    void commitLoads(InstSeqNum &youngest_inst, ThreadID tid)
11210037SARM gem5 Developers    { thread[tid].commitLoads(youngest_inst); }
1138286SAli.Saidi@ARM.com
11410037SARM gem5 Developers    /**
1158286SAli.Saidi@ARM.com     * Commits stores up until the given sequence number for a specific thread.
11610037SARM gem5 Developers     */
11710037SARM gem5 Developers    void commitStores(InstSeqNum &youngest_inst, ThreadID tid)
11810037SARM gem5 Developers    { thread[tid].commitStores(youngest_inst); }
11910037SARM gem5 Developers
12010037SARM gem5 Developers    /**
12110037SARM gem5 Developers     * Attempts to write back stores until all cache ports are used or the
12210037SARM gem5 Developers     * interface becomes blocked.
12310037SARM gem5 Developers     */
12410037SARM gem5 Developers    void writebackStores();
12510037SARM gem5 Developers    /** Same as above, but only for one thread. */
12610037SARM gem5 Developers    void writebackStores(ThreadID tid);
1278286SAli.Saidi@ARM.com
1288286SAli.Saidi@ARM.com    /**
1298286SAli.Saidi@ARM.com     * Squash instructions from a thread until the specified sequence number.
1308286SAli.Saidi@ARM.com     */
1318286SAli.Saidi@ARM.com    void squash(const InstSeqNum &squashed_num, ThreadID tid)
1328286SAli.Saidi@ARM.com    { thread[tid].squash(squashed_num); }
1338885SAli.Saidi@ARM.com
1348885SAli.Saidi@ARM.com    /** Returns whether or not there was a memory ordering violation. */
1358885SAli.Saidi@ARM.com    bool violation();
1368286SAli.Saidi@ARM.com    /**
13710037SARM gem5 Developers     * Returns whether or not there was a memory ordering violation for a
13810037SARM gem5 Developers     * specific thread.
13910037SARM gem5 Developers     */
1408286SAli.Saidi@ARM.com    bool violation(ThreadID tid)
1418286SAli.Saidi@ARM.com    { return thread[tid].violation(); }
1428286SAli.Saidi@ARM.com
1438286SAli.Saidi@ARM.com    /** Returns if a load is blocked due to the memory system for a specific
14410037SARM gem5 Developers     *  thread.
14510037SARM gem5 Developers     */
1468286SAli.Saidi@ARM.com    bool loadBlocked(ThreadID tid)
1478286SAli.Saidi@ARM.com    { return thread[tid].loadBlocked(); }
14810037SARM gem5 Developers
14910037SARM gem5 Developers    bool isLoadBlockedHandled(ThreadID tid)
15010037SARM gem5 Developers    { return thread[tid].isLoadBlockedHandled(); }
1518286SAli.Saidi@ARM.com
1522567SN/A    void setLoadBlockedHandled(ThreadID tid)
1532567SN/A    { thread[tid].setLoadBlockedHandled(); }
15410037SARM gem5 Developers
15510037SARM gem5 Developers    /** Gets the instruction that caused the memory ordering violation. */
15610037SARM gem5 Developers    DynInstPtr getMemDepViolator(ThreadID tid)
15710037SARM gem5 Developers    { return thread[tid].getMemDepViolator(); }
15810037SARM gem5 Developers
15910037SARM gem5 Developers    /** Returns the head index of the load queue for a specific thread. */
16010037SARM gem5 Developers    int getLoadHead(ThreadID tid)
16110037SARM gem5 Developers    { return thread[tid].getLoadHead(); }
16210037SARM gem5 Developers
16310037SARM gem5 Developers    /** Returns the sequence number of the head of the load queue. */
16410037SARM gem5 Developers    InstSeqNum getLoadHeadSeqNum(ThreadID tid)
16510037SARM gem5 Developers    {
16610037SARM gem5 Developers        return thread[tid].getLoadHeadSeqNum();
16710037SARM gem5 Developers    }
16810037SARM gem5 Developers
16910037SARM gem5 Developers    /** Returns the head index of the store queue. */
17010037SARM gem5 Developers    int getStoreHead(ThreadID tid)
17110037SARM gem5 Developers    { return thread[tid].getStoreHead(); }
17210037SARM gem5 Developers
17310037SARM gem5 Developers    /** Returns the sequence number of the head of the store queue. */
17410037SARM gem5 Developers    InstSeqNum getStoreHeadSeqNum(ThreadID tid)
17510037SARM gem5 Developers    {
17610037SARM gem5 Developers        return thread[tid].getStoreHeadSeqNum();
17710037SARM gem5 Developers    }
17810037SARM gem5 Developers
17910037SARM gem5 Developers    /** Returns the number of instructions in all of the queues. */
18010037SARM gem5 Developers    int getCount();
18110037SARM gem5 Developers    /** Returns the number of instructions in the queues of one thread. */
18210037SARM gem5 Developers    int getCount(ThreadID tid)
18310037SARM gem5 Developers    { return thread[tid].getCount(); }
1846757SAli.Saidi@ARM.com
1852567SN/A    /** Returns the total number of loads in the load queue. */
1868286SAli.Saidi@ARM.com    int numLoads();
1878286SAli.Saidi@ARM.com    /** Returns the total number of loads for a single thread. */
1882567SN/A    int numLoads(ThreadID tid)
1892567SN/A    { return thread[tid].numLoads(); }
19010037SARM gem5 Developers
19110037SARM gem5 Developers    /** Returns the total number of stores in the store queue. */
19210037SARM gem5 Developers    int numStores();
19310037SARM gem5 Developers    /** Returns the total number of stores for a single thread. */
19410037SARM gem5 Developers    int numStores(ThreadID tid)
1956757SAli.Saidi@ARM.com    { return thread[tid].numStores(); }
19610037SARM gem5 Developers
19710037SARM gem5 Developers    /** Returns the total number of loads that are ready. */
19810037SARM gem5 Developers    int numLoadsReady();
19910037SARM gem5 Developers    /** Returns the number of loads that are ready for a single thread. */
20010037SARM gem5 Developers    int numLoadsReady(ThreadID tid)
20110037SARM gem5 Developers    { return thread[tid].numLoadsReady(); }
20210037SARM gem5 Developers
20310037SARM gem5 Developers    /** Returns the number of free entries. */
20410037SARM gem5 Developers    unsigned numFreeEntries();
20510037SARM gem5 Developers    /** Returns the number of free entries for a specific thread. */
20610037SARM gem5 Developers    unsigned numFreeEntries(ThreadID tid);
20710037SARM gem5 Developers
20810037SARM gem5 Developers    /** Returns if the LSQ is full (either LQ or SQ is full). */
20910037SARM gem5 Developers    bool isFull();
21010037SARM gem5 Developers    /**
21110037SARM gem5 Developers     * Returns if the LSQ is full for a specific thread (either LQ or SQ is
21210037SARM gem5 Developers     * full).
21310037SARM gem5 Developers     */
21410037SARM gem5 Developers    bool isFull(ThreadID tid);
21510037SARM gem5 Developers
21610037SARM gem5 Developers    /** Returns if any of the LQs are full. */
21710037SARM gem5 Developers    bool lqFull();
21810037SARM gem5 Developers    /** Returns if the LQ of a given thread is full. */
21910037SARM gem5 Developers    bool lqFull(ThreadID tid);
22010037SARM gem5 Developers
22110037SARM gem5 Developers    /** Returns if any of the SQs are full. */
22210037SARM gem5 Developers    bool sqFull();
22310037SARM gem5 Developers    /** Returns if the SQ of a given thread is full. */
22410037SARM gem5 Developers    bool sqFull(ThreadID tid);
22510037SARM gem5 Developers
22610037SARM gem5 Developers    /**
22710037SARM gem5 Developers     * Returns if the LSQ is stalled due to a memory operation that must be
22810037SARM gem5 Developers     * replayed.
22910037SARM gem5 Developers     */
23010037SARM gem5 Developers    bool isStalled();
23110037SARM gem5 Developers    /**
23210037SARM gem5 Developers     * Returns if the LSQ of a specific thread is stalled due to a memory
23310037SARM gem5 Developers     * operation that must be replayed.
23410037SARM gem5 Developers     */
23510037SARM gem5 Developers    bool isStalled(ThreadID tid);
23610037SARM gem5 Developers
23710037SARM gem5 Developers    /** Returns whether or not there are any stores to write back to memory. */
23810037SARM gem5 Developers    bool hasStoresToWB();
23910037SARM gem5 Developers
24010037SARM gem5 Developers    /** Returns whether or not a specific thread has any stores to write back
24110037SARM gem5 Developers     * to memory.
24210037SARM gem5 Developers     */
24310037SARM gem5 Developers    bool hasStoresToWB(ThreadID tid)
24410037SARM gem5 Developers    { return thread[tid].hasStoresToWB(); }
24510037SARM gem5 Developers
24610037SARM gem5 Developers    /** Returns the number of stores a specific thread has to write back. */
2476757SAli.Saidi@ARM.com    int numStoresToWB(ThreadID tid)
2486757SAli.Saidi@ARM.com    { return thread[tid].numStoresToWB(); }
2492567SN/A
2506757SAli.Saidi@ARM.com    /** Returns if the LSQ will write back to memory this cycle. */
2512567SN/A    bool willWB();
252    /** Returns if the LSQ of a specific thread will write back to memory this
253     * cycle.
254     */
255    bool willWB(ThreadID tid)
256    { return thread[tid].willWB(); }
257
258    /** Returns if the cache is currently blocked. */
259    bool cacheBlocked()
260    { return retryTid != InvalidThreadID; }
261
262    /** Sets the retry thread id, indicating that one of the LSQUnits
263     * tried to access the cache but the cache was blocked. */
264    void setRetryTid(ThreadID tid)
265    { retryTid = tid; }
266
267    /** Debugging function to print out all instructions. */
268    void dumpInsts();
269    /** Debugging function to print out instructions from a specific thread. */
270    void dumpInsts(ThreadID tid)
271    { thread[tid].dumpInsts(); }
272
273    /** Executes a read operation, using the load specified at the load
274     * index.
275     */
276    Fault read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
277               uint8_t *data, int load_idx);
278
279    /** Executes a store operation, using the store specified at the store
280     * index.
281     */
282    Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
283                uint8_t *data, int store_idx);
284
285    /** The CPU pointer. */
286    O3CPU *cpu;
287
288    /** The IEW stage pointer. */
289    IEW *iewStage;
290
291    /** DcachePort class for this LSQ.  Handles doing the
292     * communication with the cache/memory.
293     */
294    class DcachePort : public Port
295    {
296      protected:
297        /** Pointer to LSQ. */
298        LSQ *lsq;
299
300      public:
301        /** Default constructor. */
302        DcachePort(LSQ *_lsq)
303            : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq)
304        { }
305
306        bool snoopRangeSent;
307
308        virtual void setPeer(Port *port);
309
310      protected:
311        /** Atomic version of receive.  Panics. */
312        virtual Tick recvAtomic(PacketPtr pkt);
313
314        /** Functional version of receive.  Panics. */
315        virtual void recvFunctional(PacketPtr pkt);
316
317        /** Receives status change.  Other than range changing, panics. */
318        virtual void recvStatusChange(Status status);
319
320        /** Returns the address ranges of this device. */
321        virtual void getDeviceAddressRanges(AddrRangeList &resp,
322                                            bool &snoop)
323        { resp.clear(); snoop = true; }
324
325        /** Timing version of receive.  Handles writing back and
326         * completing the load or store that has returned from
327         * memory. */
328        virtual bool recvTiming(PacketPtr pkt);
329
330        /** Handles doing a retry of the previous send. */
331        virtual void recvRetry();
332    };
333
334    /** D-cache port. */
335    DcachePort dcachePort;
336
337#if FULL_SYSTEM
338    /** Tell the CPU to update the Phys and Virt ports. */
339    void updateMemPorts() { cpu->updateMemPorts(); }
340#endif
341
342  protected:
343    /** The LSQ policy for SMT mode. */
344    LSQPolicy lsqPolicy;
345
346    /** The LSQ units for individual threads. */
347    LSQUnit thread[Impl::MaxThreads];
348
349    /** List of Active Threads in System. */
350    std::list<ThreadID> *activeThreads;
351
352    /** Total Size of LQ Entries. */
353    unsigned LQEntries;
354    /** Total Size of SQ Entries. */
355    unsigned SQEntries;
356
357    /** Max LQ Size - Used to Enforce Sharing Policies. */
358    unsigned maxLQEntries;
359
360    /** Max SQ Size - Used to Enforce Sharing Policies. */
361    unsigned maxSQEntries;
362
363    /** Number of Threads. */
364    ThreadID numThreads;
365
366    /** The thread id of the LSQ Unit that is currently waiting for a
367     * retry. */
368    ThreadID retryTid;
369};
370
371template <class Impl>
372Fault
373LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
374                uint8_t *data, int load_idx)
375{
376    ThreadID tid = req->threadId();
377
378    return thread[tid].read(req, sreqLow, sreqHigh, data, load_idx);
379}
380
381template <class Impl>
382Fault
383LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
384                 uint8_t *data, int store_idx)
385{
386    ThreadID tid = req->threadId();
387
388    return thread[tid].write(req, sreqLow, sreqHigh, data, store_idx);
389}
390
391#endif // __CPU_O3_LSQ_HH__
392