mem_dep_unit.hh revision 2307
17008Snate@binkert.org/*
27008Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan
37008Snate@binkert.org * All rights reserved.
47008Snate@binkert.org *
57008Snate@binkert.org * Redistribution and use in source and binary forms, with or without
67008Snate@binkert.org * modification, are permitted provided that the following conditions are
77008Snate@binkert.org * met: redistributions of source code must retain the above copyright
87008Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97008Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107008Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117008Snate@binkert.org * documentation and/or other materials provided with the distribution;
127008Snate@binkert.org * neither the name of the copyright holders nor the names of its
137008Snate@binkert.org * contributors may be used to endorse or promote products derived from
147008Snate@binkert.org * this software without specific prior written permission.
157008Snate@binkert.org *
167008Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177008Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187008Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197008Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207008Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217008Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227008Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237008Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247008Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257008Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267008Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277008Snate@binkert.org */
286285Snate@binkert.org
2910472Sandreas.hansson@arm.com#ifndef __CPU_O3_MEM_DEP_UNIT_HH__
3010472Sandreas.hansson@arm.com#define __CPU_O3_MEM_DEP_UNIT_HH__
318232Snate@binkert.org
329104Shestness@cs.utexas.edu#include <list>
337039Snate@binkert.org#include <set>
3411339SMichael.Lebeane@amd.com
357039Snate@binkert.org#include "base/hashmap.hh"
3611108Sdavid.hashe@amd.com#include "base/refcnt.hh"
376285Snate@binkert.org#include "base/statistics.hh"
386876Ssteve.reinhardt@amd.com#include "cpu/inst_seq.hh"
3911339SMichael.Lebeane@amd.com
406285Snate@binkert.orgstruct SNHash {
416285Snate@binkert.org    size_t operator() (const InstSeqNum &seq_num) const {
426285Snate@binkert.org        unsigned a = (unsigned)seq_num;
437039Snate@binkert.org        unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
447039Snate@binkert.org
456285Snate@binkert.org        return hash;
4611339SMichael.Lebeane@amd.com    }
477039Snate@binkert.org};
487039Snate@binkert.org
4911346Santhony.gutierrez@amd.comtemplate <class Impl>
5011346Santhony.gutierrez@amd.comclass InstructionQueue;
5111346Santhony.gutierrez@amd.com
5210518Snilay@cs.wisc.edu/**
5310518Snilay@cs.wisc.edu * Memory dependency unit class.  This holds the memory dependence predictor.
547039Snate@binkert.org * As memory operations are issued to the IQ, they are also issued to this
558615Snilay@cs.wisc.edu * unit, which then looks up the prediction as to what they are dependent
566285Snate@binkert.org * upon.  This unit must be checked prior to a memory operation being able
577544SBrad.Beckmann@amd.com * to issue.  Although this is templated, it's somewhat hard to make a generic
587544SBrad.Beckmann@amd.com * memory dependence unit.  This one is mostly for store sets; it will be
597544SBrad.Beckmann@amd.com * quite limited in what other memory dependence predictions it can also
607544SBrad.Beckmann@amd.com * utilize.  Thus this class should be most likely be rewritten for other
6111025Snilay@cs.wisc.edu * dependence prediction schemes.
6210562Sandreas.hansson@arm.com */
638615Snilay@cs.wisc.edutemplate <class MemDepPred, class Impl>
648615Snilay@cs.wisc.educlass MemDepUnit {
656285Snate@binkert.org  public:
667039Snate@binkert.org    typedef typename Impl::Params Params;
677039Snate@binkert.org    typedef typename Impl::DynInstPtr DynInstPtr;
686285Snate@binkert.org
697039Snate@binkert.org    /** Empty constructor. Must call init() prior to using in this case. */
707039Snate@binkert.org    MemDepUnit() {}
717039Snate@binkert.org
727039Snate@binkert.org    /** Constructs a MemDepUnit with given parameters. */
737039Snate@binkert.org    MemDepUnit(Params *params);
747039Snate@binkert.org
758615Snilay@cs.wisc.edu    /** Frees up any memory allocated. */
766285Snate@binkert.org    ~MemDepUnit();
7710472Sandreas.hansson@arm.com
7810472Sandreas.hansson@arm.com    /** Returns the name of the memory dependence unit. */
7911025Snilay@cs.wisc.edu    std::string name() const;
8011025Snilay@cs.wisc.edu
817453Snate@binkert.org    /** Initializes the unit with parameters and a thread id. */
827039Snate@binkert.org    void init(Params *params, int tid);
836888SBrad.Beckmann@amd.com
847453Snate@binkert.org    /** Registers statistics. */
857039Snate@binkert.org    void regStats();
866888SBrad.Beckmann@amd.com
877915SBrad.Beckmann@amd.com    void switchOut();
887915SBrad.Beckmann@amd.com
897915SBrad.Beckmann@amd.com    void takeOverFrom();
907915SBrad.Beckmann@amd.com
917039Snate@binkert.org    /** Sets the pointer to the IQ. */
926888SBrad.Beckmann@amd.com    void setIQ(InstructionQueue<Impl> *iq_ptr);
937039Snate@binkert.org
9411111Snilay@cs.wisc.edu    /** Inserts a memory instruction. */
957453Snate@binkert.org    void insert(DynInstPtr &inst);
966285Snate@binkert.org
977039Snate@binkert.org    /** Inserts a non-speculative memory instruction. */
986285Snate@binkert.org    void insertNonSpec(DynInstPtr &inst);
996285Snate@binkert.org
1007039Snate@binkert.org    /** Inserts a barrier instruction. */
1017039Snate@binkert.org    void insertBarrier(DynInstPtr &barr_inst);
1026285Snate@binkert.org
10310231Ssteve.reinhardt@amd.com    /** Indicate that an instruction has its registers ready. */
1047039Snate@binkert.org    void regsReady(DynInstPtr &inst);
1057039Snate@binkert.org
1068162SBrad.Beckmann@amd.com    /** Indicate that a non-speculative instruction is ready. */
1078162SBrad.Beckmann@amd.com    void nonSpecInstReady(DynInstPtr &inst);
1088162SBrad.Beckmann@amd.com
1098162SBrad.Beckmann@amd.com    /** Reschedules an instruction to be re-executed. */
1108162SBrad.Beckmann@amd.com    void reschedule(DynInstPtr &inst);
1118162SBrad.Beckmann@amd.com
1127039Snate@binkert.org    /** Replays all instructions that have been rescheduled by moving them to
1137039Snate@binkert.org     *  the ready list.
1147039Snate@binkert.org     */
1156285Snate@binkert.org    void replay(DynInstPtr &inst);
11610472Sandreas.hansson@arm.com
11710472Sandreas.hansson@arm.com    /** Completes a memory instruction. */
11811025Snilay@cs.wisc.edu    void completed(DynInstPtr &inst);
11911025Snilay@cs.wisc.edu
1206888SBrad.Beckmann@amd.com    /** Completes a barrier instruction. */
12111025Snilay@cs.wisc.edu    void completeBarrier(DynInstPtr &inst);
12211025Snilay@cs.wisc.edu
1236888SBrad.Beckmann@amd.com    /** Wakes any dependents of a memory instruction. */
1247453Snate@binkert.org    void wakeDependents(DynInstPtr &inst);
1257039Snate@binkert.org
1266888SBrad.Beckmann@amd.com    /** Squashes all instructions up until a given sequence number for a
1277453Snate@binkert.org     *  specific thread.
1287039Snate@binkert.org     */
1297039Snate@binkert.org    void squash(const InstSeqNum &squashed_num, unsigned tid);
1307039Snate@binkert.org
1317039Snate@binkert.org    /** Indicates an ordering violation between a store and a younger load. */
1326888SBrad.Beckmann@amd.com    void violation(DynInstPtr &store_inst, DynInstPtr &violating_load);
1337039Snate@binkert.org
1347453Snate@binkert.org    /** Issues the given instruction */
1357039Snate@binkert.org    void issue(DynInstPtr &inst);
1367453Snate@binkert.org
1377039Snate@binkert.org    /** Debugging function to dump the lists of instructions. */
1386888SBrad.Beckmann@amd.com    void dumpLists();
1397039Snate@binkert.org
14011111Snilay@cs.wisc.edu  private:
1417453Snate@binkert.org    typedef typename std::list<DynInstPtr>::iterator ListIt;
14210917Sbrandon.potter@amd.com
1438160SBrad.Beckmann@amd.com    class MemDepEntry;
1448160SBrad.Beckmann@amd.com
1458160SBrad.Beckmann@amd.com    typedef RefCountingPtr<MemDepEntry> MemDepEntryPtr;
1466285Snate@binkert.org
1476285Snate@binkert.org    /** Memory dependence entries that track memory operations, marking
1487039Snate@binkert.org     *  when the instruction is ready to execute and what instructions depend
1497039Snate@binkert.org     *  upon it.
1506285Snate@binkert.org     */
15110231Ssteve.reinhardt@amd.com    class MemDepEntry : public RefCounted {
1527039Snate@binkert.org      public:
1537039Snate@binkert.org        /** Constructs a memory dependence entry. */
1547039Snate@binkert.org        MemDepEntry(DynInstPtr &new_inst)
1557039Snate@binkert.org            : inst(new_inst), regsReady(false), memDepReady(false),
15610231Ssteve.reinhardt@amd.com              completed(false), squashed(false)
1577915SBrad.Beckmann@amd.com        {
1587915SBrad.Beckmann@amd.com            ++memdep_count;
1597915SBrad.Beckmann@amd.com
1607915SBrad.Beckmann@amd.com            DPRINTF(MemDepUnit, "Memory dependency entry created.  "
1617039Snate@binkert.org                    "memdep_count=%i\n", memdep_count);
1626285Snate@binkert.org        }
1636285Snate@binkert.org
1647039Snate@binkert.org        /** Frees any pointers. */
1657039Snate@binkert.org        ~MemDepEntry()
1666285Snate@binkert.org        {
1677039Snate@binkert.org            for (int i = 0; i < dependInsts.size(); ++i) {
1686285Snate@binkert.org                dependInsts[i] = NULL;
1696285Snate@binkert.org            }
1707039Snate@binkert.org
17110518Snilay@cs.wisc.edu            --memdep_count;
17210518Snilay@cs.wisc.edu
1739104Shestness@cs.utexas.edu            DPRINTF(MemDepUnit, "Memory dependency entry deleted.  "
1749104Shestness@cs.utexas.edu                    "memdep_count=%i\n", memdep_count);
1759104Shestness@cs.utexas.edu        }
1769104Shestness@cs.utexas.edu
1776876Ssteve.reinhardt@amd.com        /** Returns the name of the memory dependence entry. */
1786876Ssteve.reinhardt@amd.com        std::string name() const { return "memdepentry"; }
1796876Ssteve.reinhardt@amd.com
1806876Ssteve.reinhardt@amd.com        /** The instruction being tracked. */
1816876Ssteve.reinhardt@amd.com        DynInstPtr inst;
182
183        /** The iterator to the instruction's location inside the list. */
184        ListIt listIt;
185
186        /** A vector of any dependent instructions. */
187        std::vector<MemDepEntryPtr> dependInsts;
188
189        /** If the registers are ready or not. */
190        bool regsReady;
191        /** If all memory dependencies have been satisfied. */
192        bool memDepReady;
193        /** If the instruction is completed. */
194        bool completed;
195        /** If the instruction is squashed. */
196        bool squashed;
197
198        /** For debugging. */
199        static int memdep_count;
200        static int memdep_insert;
201        static int memdep_erase;
202    };
203
204    struct ltMemDepEntry {
205        bool operator() (const MemDepEntryPtr &lhs, const MemDepEntryPtr &rhs)
206        {
207            return lhs->inst->seqNum < rhs->inst->seqNum;
208        }
209    };
210
211    /** Finds the memory dependence entry in the hash map. */
212    inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
213
214    /** Moves an entry to the ready list. */
215    inline void moveToReady(MemDepEntryPtr &ready_inst_entry);
216
217    typedef m5::hash_map<InstSeqNum, MemDepEntryPtr, SNHash> MemDepHash;
218
219    typedef typename MemDepHash::iterator MemDepHashIt;
220
221    /** A hash map of all memory dependence entries. */
222    MemDepHash memDepHash;
223
224    /** A list of all instructions in the memory dependence unit. */
225    std::list<DynInstPtr> instList[Impl::MaxThreads];
226
227    /** A list of all instructions that are going to be replayed. */
228    std::list<DynInstPtr> instsToReplay;
229
230    /** The memory dependence predictor.  It is accessed upon new
231     *  instructions being added to the IQ, and responds by telling
232     *  this unit what instruction the newly added instruction is dependent
233     *  upon.
234     */
235    MemDepPred depPred;
236
237    bool loadBarrier;
238    InstSeqNum loadBarrierSN;
239    bool storeBarrier;
240    InstSeqNum storeBarrierSN;
241
242    /** Pointer to the IQ. */
243    InstructionQueue<Impl> *iqPtr;
244
245    /** The thread id of this memory dependence unit. */
246    int id;
247
248    /** Stat for number of inserted loads. */
249    Stats::Scalar<> insertedLoads;
250    /** Stat for number of inserted stores. */
251    Stats::Scalar<> insertedStores;
252    /** Stat for number of conflicting loads that had to wait for a store. */
253    Stats::Scalar<> conflictingLoads;
254    /** Stat for number of conflicting stores that had to wait for a store. */
255    Stats::Scalar<> conflictingStores;
256};
257
258#endif // __CPU_O3_MEM_DEP_UNIT_HH__
259