lsq_unit.hh revision 2307
16313Sgblack@eecs.umich.edu/*
212529Sgiacomo.travaglini@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
37093Sgblack@eecs.umich.edu * All rights reserved.
47093Sgblack@eecs.umich.edu *
57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146313Sgblack@eecs.umich.edu * this software without specific prior written permission.
156313Sgblack@eecs.umich.edu *
166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276313Sgblack@eecs.umich.edu */
286313Sgblack@eecs.umich.edu
296313Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__
306313Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__
316313Sgblack@eecs.umich.edu
326313Sgblack@eecs.umich.edu#include <map>
336313Sgblack@eecs.umich.edu#include <queue>
346313Sgblack@eecs.umich.edu#include <algorithm>
356313Sgblack@eecs.umich.edu
366313Sgblack@eecs.umich.edu#include "config/full_system.hh"
376313Sgblack@eecs.umich.edu#include "base/hashmap.hh"
386313Sgblack@eecs.umich.edu#include "cpu/inst_seq.hh"
396313Sgblack@eecs.umich.edu#include "mem/mem_interface.hh"
406313Sgblack@eecs.umich.edu//#include "mem/page_table.hh"
416313Sgblack@eecs.umich.edu#include "sim/debug.hh"
426313Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
436313Sgblack@eecs.umich.edu#include "arch/faults.hh"
447404SAli.Saidi@ARM.com
456313Sgblack@eecs.umich.edu/**
4610461SAndreas.Sandberg@ARM.com * Class that implements the actual LQ and SQ for each specific thread.
4712479SCurtis.Dunham@arm.com * Both are circular queues; load entries are freed upon committing, while
486333Sgblack@eecs.umich.edu * store entries are freed once they writeback. The LSQUnit tracks if there
4910037SARM gem5 Developers * are memory ordering violations, and also detects partial load to store
507404SAli.Saidi@ARM.com * forwarding cases (a store only has part of a load's data) that requires
516313Sgblack@eecs.umich.edu * the load to wait until the store writes back. In the former case it
5212109SRekai.GonzalezAlberquilla@arm.com * holds onto the instruction until the dependence unit looks at it, and
538232Snate@binkert.org * in the latter it stalls the LSQ until the store writes back. At that
5412109SRekai.GonzalezAlberquilla@arm.com * point the load is replayed.
559384SAndreas.Sandberg@arm.com */
5611165SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl>
576313Sgblack@eecs.umich.educlass LSQUnit {
589384SAndreas.Sandberg@arm.com  protected:
5910461SAndreas.Sandberg@ARM.com    typedef TheISA::IntReg IntReg;
606333Sgblack@eecs.umich.edu  public:
616313Sgblack@eecs.umich.edu    typedef typename Impl::Params Params;
626313Sgblack@eecs.umich.edu    typedef typename Impl::FullCPU FullCPU;
636313Sgblack@eecs.umich.edu    typedef typename Impl::DynInstPtr DynInstPtr;
646313Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::IEW IEW;
656313Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
669384SAndreas.Sandberg@arm.com
676313Sgblack@eecs.umich.edu  private:
686313Sgblack@eecs.umich.edu    class StoreCompletionEvent : public Event {
6910037SARM gem5 Developers      public:
7010037SARM gem5 Developers        /** Constructs a store completion event. */
7110037SARM gem5 Developers        StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr);
7211165SRekai.GonzalezAlberquilla@arm.com
7311165SRekai.GonzalezAlberquilla@arm.com        /** Processes the store completion event. */
7412109SRekai.GonzalezAlberquilla@arm.com        void process();
7511165SRekai.GonzalezAlberquilla@arm.com
7610461SAndreas.Sandberg@ARM.com        /** Returns the description of this event. */
7710461SAndreas.Sandberg@ARM.com        const char *description();
7810461SAndreas.Sandberg@ARM.com
7910461SAndreas.Sandberg@ARM.com      private:
8010461SAndreas.Sandberg@ARM.com        /** The store index of the store being written back. */
8110461SAndreas.Sandberg@ARM.com        int storeIdx;
8210844Sandreas.sandberg@arm.com        /** The writeback event for the store.  Needed for store
8310844Sandreas.sandberg@arm.com         * conditionals.
8410844Sandreas.sandberg@arm.com         */
8510037SARM gem5 Developers        Event *wbEvent;
8611771SCurtis.Dunham@arm.com        /** The pointer to the LSQ unit that issued the store. */
8710037SARM gem5 Developers        LSQUnit<Impl> *lsqPtr;
8810037SARM gem5 Developers    };
8910037SARM gem5 Developers
9013173Sgiacomo.travaglini@arm.com    friend class StoreCompletionEvent;
9110037SARM gem5 Developers
9213114Sgiacomo.travaglini@arm.com  public:
9310037SARM gem5 Developers    /** Constructs an LSQ unit. init() must be called prior to use. */
9412714Sgiacomo.travaglini@arm.com    LSQUnit();
9512714Sgiacomo.travaglini@arm.com
9612714Sgiacomo.travaglini@arm.com    /** Initializes the LSQ unit with the specified number of entries. */
9712714Sgiacomo.travaglini@arm.com    void init(Params *params, unsigned maxLQEntries,
9812714Sgiacomo.travaglini@arm.com              unsigned maxSQEntries, unsigned id);
9912714Sgiacomo.travaglini@arm.com
10012478SCurtis.Dunham@arm.com    /** Returns the name of the LSQ unit. */
10110037SARM gem5 Developers    std::string name() const;
10212477SCurtis.Dunham@arm.com
10312477SCurtis.Dunham@arm.com    /** Sets the CPU pointer. */
10412478SCurtis.Dunham@arm.com    void setCPU(FullCPU *cpu_ptr)
10512478SCurtis.Dunham@arm.com    { cpu = cpu_ptr; }
10612478SCurtis.Dunham@arm.com
10712478SCurtis.Dunham@arm.com    /** Sets the IEW stage pointer. */
10812478SCurtis.Dunham@arm.com    void setIEW(IEW *iew_ptr)
10912478SCurtis.Dunham@arm.com    { iewStage = iew_ptr; }
11012478SCurtis.Dunham@arm.com
11112478SCurtis.Dunham@arm.com    /** Sets the page table pointer. */
11212478SCurtis.Dunham@arm.com//    void setPageTable(PageTable *pt_ptr);
11312478SCurtis.Dunham@arm.com
11412478SCurtis.Dunham@arm.com    void switchOut();
11512478SCurtis.Dunham@arm.com
11612478SCurtis.Dunham@arm.com    void takeOverFrom();
11712478SCurtis.Dunham@arm.com
11812478SCurtis.Dunham@arm.com    bool isSwitchedOut() { return switchedOut; }
11912478SCurtis.Dunham@arm.com
12010037SARM gem5 Developers    /** Ticks the LSQ unit, which in this case only resets the number of
12110037SARM gem5 Developers     * used cache ports.
12212477SCurtis.Dunham@arm.com     * @todo: Move the number of used ports up to the LSQ level so it can
12312479SCurtis.Dunham@arm.com     * be shared by all LSQ units.
12412477SCurtis.Dunham@arm.com     */
12512477SCurtis.Dunham@arm.com    void tick() { usedPorts = 0; }
12612477SCurtis.Dunham@arm.com
12712479SCurtis.Dunham@arm.com    /** Inserts an instruction. */
12812477SCurtis.Dunham@arm.com    void insert(DynInstPtr &inst);
12912477SCurtis.Dunham@arm.com    /** Inserts a load instruction. */
13012477SCurtis.Dunham@arm.com    void insertLoad(DynInstPtr &load_inst);
13112477SCurtis.Dunham@arm.com    /** Inserts a store instruction. */
13212477SCurtis.Dunham@arm.com    void insertStore(DynInstPtr &store_inst);
13312477SCurtis.Dunham@arm.com
13412477SCurtis.Dunham@arm.com    /** Executes a load instruction. */
13512478SCurtis.Dunham@arm.com    Fault executeLoad(DynInstPtr &inst);
13612478SCurtis.Dunham@arm.com
13712478SCurtis.Dunham@arm.com    Fault executeLoad(int lq_idx);
13812478SCurtis.Dunham@arm.com    /** Executes a store instruction. */
13912478SCurtis.Dunham@arm.com    Fault executeStore(DynInstPtr &inst);
14012478SCurtis.Dunham@arm.com
14112478SCurtis.Dunham@arm.com    /** Commits the head load. */
14212478SCurtis.Dunham@arm.com    void commitLoad();
14312478SCurtis.Dunham@arm.com    /** Commits a specific load, given by the sequence number. */
14412478SCurtis.Dunham@arm.com    void commitLoad(InstSeqNum &inst);
14512478SCurtis.Dunham@arm.com    /** Commits loads older than a specific sequence number. */
14612478SCurtis.Dunham@arm.com    void commitLoads(InstSeqNum &youngest_inst);
14712478SCurtis.Dunham@arm.com
14812478SCurtis.Dunham@arm.com    /** Commits stores older than a specific sequence number. */
14912478SCurtis.Dunham@arm.com    void commitStores(InstSeqNum &youngest_inst);
15012478SCurtis.Dunham@arm.com
15112479SCurtis.Dunham@arm.com    /** Writes back stores. */
15212479SCurtis.Dunham@arm.com    void writebackStores();
15312479SCurtis.Dunham@arm.com
15412479SCurtis.Dunham@arm.com    // @todo: Include stats in the LSQ unit.
15512479SCurtis.Dunham@arm.com    //void regStats();
15612479SCurtis.Dunham@arm.com
15712479SCurtis.Dunham@arm.com    /** Clears all the entries in the LQ. */
15812479SCurtis.Dunham@arm.com    void clearLQ();
15912479SCurtis.Dunham@arm.com
16012479SCurtis.Dunham@arm.com    /** Clears all the entries in the SQ. */
16112479SCurtis.Dunham@arm.com    void clearSQ();
16212479SCurtis.Dunham@arm.com
16312479SCurtis.Dunham@arm.com    /** Resizes the LQ to a given size. */
16412479SCurtis.Dunham@arm.com    void resizeLQ(unsigned size);
16512479SCurtis.Dunham@arm.com
16612479SCurtis.Dunham@arm.com    /** Resizes the SQ to a given size. */
16712479SCurtis.Dunham@arm.com    void resizeSQ(unsigned size);
16812479SCurtis.Dunham@arm.com
16912479SCurtis.Dunham@arm.com    /** Squashes all instructions younger than a specific sequence number. */
17012479SCurtis.Dunham@arm.com    void squash(const InstSeqNum &squashed_num);
17112479SCurtis.Dunham@arm.com
17212479SCurtis.Dunham@arm.com    /** Returns if there is a memory ordering violation. Value is reset upon
17312479SCurtis.Dunham@arm.com     * call to getMemDepViolator().
17412479SCurtis.Dunham@arm.com     */
17512479SCurtis.Dunham@arm.com    bool violation() { return memDepViolator; }
17612479SCurtis.Dunham@arm.com
17712479SCurtis.Dunham@arm.com    /** Returns the memory ordering violator. */
17812479SCurtis.Dunham@arm.com    DynInstPtr getMemDepViolator();
17912479SCurtis.Dunham@arm.com
18012479SCurtis.Dunham@arm.com    /** Returns if a load became blocked due to the memory system.  It clears
18112479SCurtis.Dunham@arm.com     *  the bool's value upon this being called.
18212479SCurtis.Dunham@arm.com     */
18312479SCurtis.Dunham@arm.com    bool loadBlocked()
18412479SCurtis.Dunham@arm.com    { return isLoadBlocked; }
18512479SCurtis.Dunham@arm.com
18612479SCurtis.Dunham@arm.com    void clearLoadBlocked()
18712479SCurtis.Dunham@arm.com    { isLoadBlocked = false; }
18812479SCurtis.Dunham@arm.com
18912479SCurtis.Dunham@arm.com    bool isLoadBlockedHandled()
19012479SCurtis.Dunham@arm.com    { return loadBlockedHandled; }
19112479SCurtis.Dunham@arm.com
19212479SCurtis.Dunham@arm.com    void setLoadBlockedHandled()
19312479SCurtis.Dunham@arm.com    { loadBlockedHandled = true; }
19412479SCurtis.Dunham@arm.com
19512479SCurtis.Dunham@arm.com    /** Returns the number of free entries (min of free LQ and SQ entries). */
19612479SCurtis.Dunham@arm.com    unsigned numFreeEntries();
19712479SCurtis.Dunham@arm.com
19812479SCurtis.Dunham@arm.com    /** Returns the number of loads ready to execute. */
19912479SCurtis.Dunham@arm.com    int numLoadsReady();
20012479SCurtis.Dunham@arm.com
20112479SCurtis.Dunham@arm.com    /** Returns the number of loads in the LQ. */
20212479SCurtis.Dunham@arm.com    int numLoads() { return loads; }
20312479SCurtis.Dunham@arm.com
20412479SCurtis.Dunham@arm.com    /** Returns the number of stores in the SQ. */
20512479SCurtis.Dunham@arm.com    int numStores() { return stores; }
20612479SCurtis.Dunham@arm.com
20712479SCurtis.Dunham@arm.com    /** Returns if either the LQ or SQ is full. */
20812479SCurtis.Dunham@arm.com    bool isFull() { return lqFull() || sqFull(); }
20912668Sgiacomo.travaglini@arm.com
21012668Sgiacomo.travaglini@arm.com    /** Returns if the LQ is full. */
21112668Sgiacomo.travaglini@arm.com    bool lqFull() { return loads >= (LQEntries - 1); }
21212668Sgiacomo.travaglini@arm.com
21312668Sgiacomo.travaglini@arm.com    /** Returns if the SQ is full. */
21412479SCurtis.Dunham@arm.com    bool sqFull() { return stores >= (SQEntries - 1); }
21512479SCurtis.Dunham@arm.com
21612479SCurtis.Dunham@arm.com    /** Debugging function to dump instructions in the LSQ. */
21712479SCurtis.Dunham@arm.com    void dumpInsts();
21812479SCurtis.Dunham@arm.com
21912479SCurtis.Dunham@arm.com    /** Returns the number of instructions in the LSQ. */
22012479SCurtis.Dunham@arm.com    unsigned getCount() { return loads + stores; }
22112479SCurtis.Dunham@arm.com
22212479SCurtis.Dunham@arm.com    /** Returns if there are any stores to writeback. */
22312479SCurtis.Dunham@arm.com    bool hasStoresToWB() { return storesToWB; }
22412479SCurtis.Dunham@arm.com
22512479SCurtis.Dunham@arm.com    /** Returns the number of stores to writeback. */
22612479SCurtis.Dunham@arm.com    int numStoresToWB() { return storesToWB; }
22712668Sgiacomo.travaglini@arm.com
22812668Sgiacomo.travaglini@arm.com    /** Returns if the LSQ unit will writeback on this cycle. */
22912668Sgiacomo.travaglini@arm.com    bool willWB() { return storeQueue[storeWBIdx].canWB &&
23012668Sgiacomo.travaglini@arm.com                        !storeQueue[storeWBIdx].completed &&
23112668Sgiacomo.travaglini@arm.com                        !dcacheInterface->isBlocked(); }
23213395Sgiacomo.travaglini@arm.com
23313395Sgiacomo.travaglini@arm.com  private:
23413395Sgiacomo.travaglini@arm.com    /** Completes the store at the specified index. */
23513395Sgiacomo.travaglini@arm.com    void completeStore(int store_idx);
23613395Sgiacomo.travaglini@arm.com
23712479SCurtis.Dunham@arm.com    /** Increments the given store index (circular queue). */
23812479SCurtis.Dunham@arm.com    inline void incrStIdx(int &store_idx);
23912479SCurtis.Dunham@arm.com    /** Decrements the given store index (circular queue). */
24012479SCurtis.Dunham@arm.com    inline void decrStIdx(int &store_idx);
24112479SCurtis.Dunham@arm.com    /** Increments the given load index (circular queue). */
24212479SCurtis.Dunham@arm.com    inline void incrLdIdx(int &load_idx);
24312479SCurtis.Dunham@arm.com    /** Decrements the given load index (circular queue). */
24412479SCurtis.Dunham@arm.com    inline void decrLdIdx(int &load_idx);
24512479SCurtis.Dunham@arm.com
24612479SCurtis.Dunham@arm.com  private:
24712479SCurtis.Dunham@arm.com    /** Pointer to the CPU. */
24812479SCurtis.Dunham@arm.com    FullCPU *cpu;
24912479SCurtis.Dunham@arm.com
25012479SCurtis.Dunham@arm.com    /** Pointer to the IEW stage. */
25112479SCurtis.Dunham@arm.com    IEW *iewStage;
25212479SCurtis.Dunham@arm.com
25312479SCurtis.Dunham@arm.com    /** Pointer to the D-cache. */
25412479SCurtis.Dunham@arm.com    MemInterface *dcacheInterface;
25512479SCurtis.Dunham@arm.com
25612479SCurtis.Dunham@arm.com    /** Pointer to the page table. */
25712479SCurtis.Dunham@arm.com//    PageTable *pTable;
25812479SCurtis.Dunham@arm.com
25912479SCurtis.Dunham@arm.com  public:
26012479SCurtis.Dunham@arm.com    struct SQEntry {
26112479SCurtis.Dunham@arm.com        /** Constructs an empty store queue entry. */
26212479SCurtis.Dunham@arm.com        SQEntry()
26312479SCurtis.Dunham@arm.com            : inst(NULL), req(NULL), size(0), data(0),
26412479SCurtis.Dunham@arm.com              canWB(0), committed(0), completed(0)
26512479SCurtis.Dunham@arm.com        { }
26612479SCurtis.Dunham@arm.com
26712479SCurtis.Dunham@arm.com        /** Constructs a store queue entry for a given instruction. */
26812479SCurtis.Dunham@arm.com        SQEntry(DynInstPtr &_inst)
26912479SCurtis.Dunham@arm.com            : inst(_inst), req(NULL), size(0), data(0),
27012479SCurtis.Dunham@arm.com              canWB(0), committed(0), completed(0)
27112479SCurtis.Dunham@arm.com        { }
27212479SCurtis.Dunham@arm.com
27312479SCurtis.Dunham@arm.com        /** The store instruction. */
27412479SCurtis.Dunham@arm.com        DynInstPtr inst;
27512479SCurtis.Dunham@arm.com        /** The memory request for the store. */
27612479SCurtis.Dunham@arm.com        MemReqPtr req;
27712479SCurtis.Dunham@arm.com        /** The size of the store. */
27812479SCurtis.Dunham@arm.com        int size;
27912479SCurtis.Dunham@arm.com        /** The store data. */
28012479SCurtis.Dunham@arm.com        IntReg data;
28112479SCurtis.Dunham@arm.com        /** Whether or not the store can writeback. */
28212479SCurtis.Dunham@arm.com        bool canWB;
28312479SCurtis.Dunham@arm.com        /** Whether or not the store is committed. */
28412479SCurtis.Dunham@arm.com        bool committed;
28512479SCurtis.Dunham@arm.com        /** Whether or not the store is completed. */
28612479SCurtis.Dunham@arm.com        bool completed;
28712479SCurtis.Dunham@arm.com    };
28812479SCurtis.Dunham@arm.com/*
28912479SCurtis.Dunham@arm.com    enum Status {
29012479SCurtis.Dunham@arm.com        Running,
29112479SCurtis.Dunham@arm.com        Idle,
29212479SCurtis.Dunham@arm.com        DcacheMissStall,
29312479SCurtis.Dunham@arm.com        DcacheMissSwitch
29412479SCurtis.Dunham@arm.com    };
29512479SCurtis.Dunham@arm.com*/
29612479SCurtis.Dunham@arm.com  private:
29712479SCurtis.Dunham@arm.com    /** The LSQUnit thread id. */
29812479SCurtis.Dunham@arm.com    unsigned lsqID;
29912479SCurtis.Dunham@arm.com
30012479SCurtis.Dunham@arm.com    /** The status of the LSQ unit. */
30112479SCurtis.Dunham@arm.com//    Status _status;
30212479SCurtis.Dunham@arm.com
30312479SCurtis.Dunham@arm.com    /** The store queue. */
30412479SCurtis.Dunham@arm.com    std::vector<SQEntry> storeQueue;
30512479SCurtis.Dunham@arm.com
30612479SCurtis.Dunham@arm.com    /** The load queue. */
30712479SCurtis.Dunham@arm.com    std::vector<DynInstPtr> loadQueue;
30812479SCurtis.Dunham@arm.com
30912479SCurtis.Dunham@arm.com    // Consider making these 16 bits
31012479SCurtis.Dunham@arm.com    /** The number of LQ entries. */
31112479SCurtis.Dunham@arm.com    unsigned LQEntries;
31212479SCurtis.Dunham@arm.com    /** The number of SQ entries. */
31312479SCurtis.Dunham@arm.com    unsigned SQEntries;
31412479SCurtis.Dunham@arm.com
31512479SCurtis.Dunham@arm.com    /** The number of load instructions in the LQ. */
31612479SCurtis.Dunham@arm.com    int loads;
31712479SCurtis.Dunham@arm.com    /** The number of store instructions in the SQ (excludes those waiting to
31812479SCurtis.Dunham@arm.com     * writeback).
31912479SCurtis.Dunham@arm.com     */
32012479SCurtis.Dunham@arm.com    int stores;
32112479SCurtis.Dunham@arm.com    /** The number of store instructions in the SQ waiting to writeback. */
32212479SCurtis.Dunham@arm.com    int storesToWB;
32312479SCurtis.Dunham@arm.com
32412479SCurtis.Dunham@arm.com    /** The index of the head instruction in the LQ. */
32512479SCurtis.Dunham@arm.com    int loadHead;
32612479SCurtis.Dunham@arm.com    /** The index of the tail instruction in the LQ. */
32712479SCurtis.Dunham@arm.com    int loadTail;
32812479SCurtis.Dunham@arm.com
32912479SCurtis.Dunham@arm.com    /** The index of the head instruction in the SQ. */
33012479SCurtis.Dunham@arm.com    int storeHead;
33112479SCurtis.Dunham@arm.com    /** The index of the first instruction that is ready to be written back,
33212479SCurtis.Dunham@arm.com     * and has not yet been written back.
33312479SCurtis.Dunham@arm.com     */
33412479SCurtis.Dunham@arm.com    int storeWBIdx;
33512479SCurtis.Dunham@arm.com    /** The index of the tail instruction in the SQ. */
33612479SCurtis.Dunham@arm.com    int storeTail;
33712479SCurtis.Dunham@arm.com
33812479SCurtis.Dunham@arm.com    /// @todo Consider moving to a more advanced model with write vs read ports
33912479SCurtis.Dunham@arm.com    /** The number of cache ports available each cycle. */
34012479SCurtis.Dunham@arm.com    int cachePorts;
34112479SCurtis.Dunham@arm.com
34212479SCurtis.Dunham@arm.com    /** The number of used cache ports in this cycle. */
34312479SCurtis.Dunham@arm.com    int usedPorts;
34412479SCurtis.Dunham@arm.com
34512479SCurtis.Dunham@arm.com    bool switchedOut;
34612479SCurtis.Dunham@arm.com
34712479SCurtis.Dunham@arm.com    //list<InstSeqNum> mshrSeqNums;
34812479SCurtis.Dunham@arm.com
34912479SCurtis.Dunham@arm.com     //Stats::Scalar<> dcacheStallCycles;
35012479SCurtis.Dunham@arm.com    Counter lastDcacheStall;
35112479SCurtis.Dunham@arm.com
35210037SARM gem5 Developers    /** Wire to read information from the issue stage time queue. */
35310037SARM gem5 Developers    typename TimeBuffer<IssueStruct>::wire fromIssue;
35412477SCurtis.Dunham@arm.com
35512479SCurtis.Dunham@arm.com    // Make these per thread?
35612479SCurtis.Dunham@arm.com    /** Whether or not the LSQ is stalled. */
35712477SCurtis.Dunham@arm.com    bool stalled;
35810037SARM gem5 Developers    /** The store that causes the stall due to partial store to load
35912477SCurtis.Dunham@arm.com     * forwarding.
36010037SARM gem5 Developers     */
3616333Sgblack@eecs.umich.edu    InstSeqNum stallingStoreIsn;
3626718Sgblack@eecs.umich.edu    /** The index of the above store. */
3636718Sgblack@eecs.umich.edu    int stallingLoadIdx;
3646718Sgblack@eecs.umich.edu
3656718Sgblack@eecs.umich.edu    /** Whether or not a load is blocked due to the memory system.  It is
3666718Sgblack@eecs.umich.edu     *  cleared when this value is checked via loadBlocked().
36710037SARM gem5 Developers     */
36810037SARM gem5 Developers    bool isLoadBlocked;
36910037SARM gem5 Developers
37010037SARM gem5 Developers    bool loadBlockedHandled;
37110037SARM gem5 Developers
37210037SARM gem5 Developers    InstSeqNum blockedLoadSeqNum;
37310037SARM gem5 Developers
37410037SARM gem5 Developers    /** The oldest faulting load instruction. */
37510037SARM gem5 Developers    DynInstPtr loadFaultInst;
37610037SARM gem5 Developers    /** The oldest faulting store instruction. */
37710037SARM gem5 Developers    DynInstPtr storeFaultInst;
37810037SARM gem5 Developers
37910037SARM gem5 Developers    /** The oldest load that caused a memory ordering violation. */
38010037SARM gem5 Developers    DynInstPtr memDepViolator;
38110037SARM gem5 Developers
38210037SARM gem5 Developers    // Will also need how many read/write ports the Dcache has.  Or keep track
38310037SARM gem5 Developers    // of that in stage that is one level up, and only call executeLoad/Store
38410037SARM gem5 Developers    // the appropriate number of times.
38510037SARM gem5 Developers/*
38610037SARM gem5 Developers    // total number of loads forwaded from LSQ stores
38710037SARM gem5 Developers    Stats::Vector<> lsq_forw_loads;
38810037SARM gem5 Developers
38910037SARM gem5 Developers    // total number of loads ignored due to invalid addresses
39010037SARM gem5 Developers    Stats::Vector<> inv_addr_loads;
39110037SARM gem5 Developers
39210037SARM gem5 Developers    // total number of software prefetches ignored due to invalid addresses
39310037SARM gem5 Developers    Stats::Vector<> inv_addr_swpfs;
39410037SARM gem5 Developers
39510037SARM gem5 Developers    // total non-speculative bogus addresses seen (debug var)
39610037SARM gem5 Developers    Counter sim_invalid_addrs;
39710037SARM gem5 Developers    Stats::Vector<> fu_busy;  //cumulative fu busy
39810037SARM gem5 Developers
3996718Sgblack@eecs.umich.edu    // ready loads blocked due to memory disambiguation
4006718Sgblack@eecs.umich.edu    Stats::Vector<> lsq_blocked_loads;
4016313Sgblack@eecs.umich.edu
40210844Sandreas.sandberg@arm.com    Stats::Scalar<> lsqInversion;
40310037SARM gem5 Developers*/
40410037SARM gem5 Developers  public:
40510037SARM gem5 Developers    /** Executes the load at the given index. */
40610037SARM gem5 Developers    template <class T>
40710037SARM gem5 Developers    Fault read(MemReqPtr &req, T &data, int load_idx);
40810037SARM gem5 Developers
40910037SARM gem5 Developers    /** Executes the store at the given index. */
41010037SARM gem5 Developers    template <class T>
41110037SARM gem5 Developers    Fault write(MemReqPtr &req, T &data, int store_idx);
41210037SARM gem5 Developers
41310037SARM gem5 Developers    /** Returns the index of the head load instruction. */
41410037SARM gem5 Developers    int getLoadHead() { return loadHead; }
41510037SARM gem5 Developers    /** Returns the sequence number of the head load instruction. */
4166313Sgblack@eecs.umich.edu    InstSeqNum getLoadHeadSeqNum()
4177427Sgblack@eecs.umich.edu    {
41813114Sgiacomo.travaglini@arm.com        if (loadQueue[loadHead]) {
41913114Sgiacomo.travaglini@arm.com            return loadQueue[loadHead]->seqNum;
42013393Sgiacomo.travaglini@arm.com        } else {
42110037SARM gem5 Developers            return 0;
42213114Sgiacomo.travaglini@arm.com        }
42313114Sgiacomo.travaglini@arm.com
4246313Sgblack@eecs.umich.edu    }
42513114Sgiacomo.travaglini@arm.com
42610035Sandreas.hansson@arm.com    /** Returns the index of the head store instruction. */
4277405SAli.Saidi@ARM.com    int getStoreHead() { return storeHead; }
4287405SAli.Saidi@ARM.com    /** Returns the sequence number of the head store instruction. */
4297405SAli.Saidi@ARM.com    InstSeqNum getStoreHeadSeqNum()
4306313Sgblack@eecs.umich.edu    {
43112106SRekai.GonzalezAlberquilla@arm.com        if (storeQueue[storeHead].inst) {
43212106SRekai.GonzalezAlberquilla@arm.com            return storeQueue[storeHead].inst->seqNum;
43312106SRekai.GonzalezAlberquilla@arm.com        } else {
43412106SRekai.GonzalezAlberquilla@arm.com            return 0;
43512106SRekai.GonzalezAlberquilla@arm.com        }
43612106SRekai.GonzalezAlberquilla@arm.com
43712106SRekai.GonzalezAlberquilla@arm.com    }
43812106SRekai.GonzalezAlberquilla@arm.com
43912109SRekai.GonzalezAlberquilla@arm.com    /** Returns whether or not the LSQ unit is stalled. */
44012109SRekai.GonzalezAlberquilla@arm.com    bool isStalled()  { return stalled; }
44112109SRekai.GonzalezAlberquilla@arm.com};
44212109SRekai.GonzalezAlberquilla@arm.com
44312106SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl>
44412106SRekai.GonzalezAlberquilla@arm.comtemplate <class T>
44512106SRekai.GonzalezAlberquilla@arm.comFault
44612106SRekai.GonzalezAlberquilla@arm.comLSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
44712106SRekai.GonzalezAlberquilla@arm.com{
44812106SRekai.GonzalezAlberquilla@arm.com    //Depending on issue2execute delay a squashed load could
44912106SRekai.GonzalezAlberquilla@arm.com    //execute if it is found to be squashed in the same
45012106SRekai.GonzalezAlberquilla@arm.com    //cycle it is scheduled to execute
4516313Sgblack@eecs.umich.edu    assert(loadQueue[load_idx]);
45210035Sandreas.hansson@arm.com
4536313Sgblack@eecs.umich.edu    if (loadQueue[load_idx]->isExecuted()) {
4546718Sgblack@eecs.umich.edu        panic("Should not reach this point with split ops!");
4556718Sgblack@eecs.umich.edu        memcpy(&data,req->data,req->size);
4566718Sgblack@eecs.umich.edu
4576726Sgblack@eecs.umich.edu        return NoFault;
4586726Sgblack@eecs.umich.edu    }
45910037SARM gem5 Developers
46010037SARM gem5 Developers    // Make sure this isn't an uncacheable access
46110037SARM gem5 Developers    // A bit of a hackish way to get uncached accesses to work only if they're
46210037SARM gem5 Developers    // at the head of the LSQ and are ready to commit (at the head of the ROB
46310037SARM gem5 Developers    // too).
46410037SARM gem5 Developers    // @todo: Fix uncached accesses.
46510037SARM gem5 Developers    if (req->flags & UNCACHEABLE &&
46610037SARM gem5 Developers        (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) {
46710037SARM gem5 Developers        iewStage->rescheduleMemInst(loadQueue[load_idx]);
46811574SCurtis.Dunham@arm.com        return TheISA::genMachineCheckFault();
46911574SCurtis.Dunham@arm.com    }
47010037SARM gem5 Developers
47110037SARM gem5 Developers    // Check the SQ for any previous stores that might lead to forwarding
47210037SARM gem5 Developers    int store_idx = loadQueue[load_idx]->sqIdx;
47310037SARM gem5 Developers
47410037SARM gem5 Developers    int store_size = 0;
47510037SARM gem5 Developers
47613020Sshunhsingou@google.com    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
47710037SARM gem5 Developers            "storeHead: %i addr: %#x\n",
4786718Sgblack@eecs.umich.edu            load_idx, store_idx, storeHead, req->paddr);
47910037SARM gem5 Developers
4806718Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
4816313Sgblack@eecs.umich.edu    if (req->flags & LOCKED) {
4826313Sgblack@eecs.umich.edu        cpu->lockAddr = req->paddr;
4836313Sgblack@eecs.umich.edu        cpu->lockFlag = true;
48410035Sandreas.hansson@arm.com    }
4856313Sgblack@eecs.umich.edu#endif
48610338SCurtis.Dunham@arm.com
4876313Sgblack@eecs.umich.edu    while (store_idx != -1) {
4886313Sgblack@eecs.umich.edu        // End once we've reached the top of the LSQ
4896313Sgblack@eecs.umich.edu        if (store_idx == storeWBIdx) {
4909920Syasuko.eckert@amd.com            break;
49112109SRekai.GonzalezAlberquilla@arm.com        }
49212109SRekai.GonzalezAlberquilla@arm.com
49312109SRekai.GonzalezAlberquilla@arm.com        // Move the index to one younger
49412109SRekai.GonzalezAlberquilla@arm.com        if (--store_idx < 0)
49512109SRekai.GonzalezAlberquilla@arm.com            store_idx += SQEntries;
49612109SRekai.GonzalezAlberquilla@arm.com
49712109SRekai.GonzalezAlberquilla@arm.com        assert(storeQueue[store_idx].inst);
49812109SRekai.GonzalezAlberquilla@arm.com
49912109SRekai.GonzalezAlberquilla@arm.com        store_size = storeQueue[store_idx].size;
50012109SRekai.GonzalezAlberquilla@arm.com
50112109SRekai.GonzalezAlberquilla@arm.com        if (store_size == 0)
50212109SRekai.GonzalezAlberquilla@arm.com            continue;
50312109SRekai.GonzalezAlberquilla@arm.com
50412109SRekai.GonzalezAlberquilla@arm.com        // Check if the store data is within the lower and upper bounds of
50510035Sandreas.hansson@arm.com        // addresses that the request needs.
5069920Syasuko.eckert@amd.com        bool store_has_lower_limit =
50710338SCurtis.Dunham@arm.com            req->vaddr >= storeQueue[store_idx].inst->effAddr;
5089920Syasuko.eckert@amd.com        bool store_has_upper_limit =
5099920Syasuko.eckert@amd.com            (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr +
5109920Syasuko.eckert@amd.com                                         store_size);
5117614Sminkyu.jeong@arm.com        bool lower_load_has_store_part =
51210035Sandreas.hansson@arm.com            req->vaddr < (storeQueue[store_idx].inst->effAddr +
5137614Sminkyu.jeong@arm.com                           store_size);
51410338SCurtis.Dunham@arm.com        bool upper_load_has_store_part =
51510037SARM gem5 Developers            (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr;
51610037SARM gem5 Developers
5177614Sminkyu.jeong@arm.com        // If the store's data has all of the data needed, we can forward.
5187614Sminkyu.jeong@arm.com        if (store_has_lower_limit && store_has_upper_limit) {
5197614Sminkyu.jeong@arm.com
52010037SARM gem5 Developers            int shift_amt = req->vaddr & (store_size - 1);
52110037SARM gem5 Developers            // Assumes byte addressing
52210037SARM gem5 Developers            shift_amt = shift_amt << 3;
52310037SARM gem5 Developers
52410037SARM gem5 Developers            // Cast this to type T?
52510037SARM gem5 Developers            data = storeQueue[store_idx].data >> shift_amt;
52610037SARM gem5 Developers
52710037SARM gem5 Developers            req->cmd = Read;
52810037SARM gem5 Developers            assert(!req->completionEvent);
52910037SARM gem5 Developers            req->completionEvent = NULL;
53010037SARM gem5 Developers            req->time = curTick;
53110037SARM gem5 Developers            assert(!req->data);
53210037SARM gem5 Developers            req->data = new uint8_t[64];
53310037SARM gem5 Developers
53410037SARM gem5 Developers            memcpy(req->data, &data, req->size);
53510037SARM gem5 Developers
5367614Sminkyu.jeong@arm.com            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
5377614Sminkyu.jeong@arm.com                    "addr %#x, data %#x\n",
53810037SARM gem5 Developers                    store_idx, req->vaddr, *(req->data));
5397614Sminkyu.jeong@arm.com
5407614Sminkyu.jeong@arm.com            typename IEW::LdWritebackEvent *wb =
54110037SARM gem5 Developers                new typename IEW::LdWritebackEvent(loadQueue[load_idx],
5427614Sminkyu.jeong@arm.com                                                   iewStage);
5437614Sminkyu.jeong@arm.com
54410037SARM gem5 Developers            // We'll say this has a 1 cycle load-store forwarding latency
5457614Sminkyu.jeong@arm.com            // for now.
5467614Sminkyu.jeong@arm.com            // @todo: Need to make this a parameter.
54710037SARM gem5 Developers            wb->schedule(curTick);
5487614Sminkyu.jeong@arm.com
5497614Sminkyu.jeong@arm.com            // Should keep track of stat for forwarded data
55010037SARM gem5 Developers            return NoFault;
5517614Sminkyu.jeong@arm.com        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
5527614Sminkyu.jeong@arm.com                   (store_has_upper_limit && upper_load_has_store_part) ||
55310037SARM gem5 Developers                   (lower_load_has_store_part && upper_load_has_store_part)) {
55410037SARM gem5 Developers            // This is the partial store-load forwarding case where a store
55510037SARM gem5 Developers            // has only part of the load's data.
55610037SARM gem5 Developers
5577614Sminkyu.jeong@arm.com            // If it's already been written back, then don't worry about
5587614Sminkyu.jeong@arm.com            // stalling on it.
55910037SARM gem5 Developers            if (storeQueue[store_idx].completed) {
5607614Sminkyu.jeong@arm.com                continue;
5617614Sminkyu.jeong@arm.com            }
5627614Sminkyu.jeong@arm.com
5637614Sminkyu.jeong@arm.com            // Must stall load and force it to retry, so long as it's the oldest
56410037SARM gem5 Developers            // load that needs to do so.
5657614Sminkyu.jeong@arm.com            if (!stalled ||
5667614Sminkyu.jeong@arm.com                (stalled &&
56710037SARM gem5 Developers                 loadQueue[load_idx]->seqNum <
56810037SARM gem5 Developers                 loadQueue[stallingLoadIdx]->seqNum)) {
56910037SARM gem5 Developers                stalled = true;
57010037SARM gem5 Developers                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
57110037SARM gem5 Developers                stallingLoadIdx = load_idx;
57210037SARM gem5 Developers            }
57310037SARM gem5 Developers
57410037SARM gem5 Developers            // Tell IQ/mem dep unit that this instruction will need to be
57510037SARM gem5 Developers            // rescheduled eventually
57610037SARM gem5 Developers            iewStage->rescheduleMemInst(loadQueue[load_idx]);
57710037SARM gem5 Developers
57810037SARM gem5 Developers            // Do not generate a writeback event as this instruction is not
57910037SARM gem5 Developers            // complete.
58010037SARM gem5 Developers
58110037SARM gem5 Developers            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
58210037SARM gem5 Developers                    "Store idx %i to load addr %#x\n",
58310037SARM gem5 Developers                    store_idx, req->vaddr);
58410037SARM gem5 Developers
58510037SARM gem5 Developers            return NoFault;
58610037SARM gem5 Developers        }
58710037SARM gem5 Developers    }
58810037SARM gem5 Developers
58910037SARM gem5 Developers
59010037SARM gem5 Developers    // If there's no forwarding case, then go access memory
59110037SARM gem5 Developers    DynInstPtr inst = loadQueue[load_idx];
59210037SARM gem5 Developers
59310037SARM gem5 Developers    DPRINTF(LSQUnit, "Doing functional access for inst PC %#x\n",
59410037SARM gem5 Developers            loadQueue[load_idx]->readPC());
59510037SARM gem5 Developers    assert(!req->data);
59610037SARM gem5 Developers    req->cmd = Read;
59710037SARM gem5 Developers    req->completionEvent = NULL;
59810037SARM gem5 Developers    req->time = curTick;
59910037SARM gem5 Developers    req->data = new uint8_t[64];
60010037SARM gem5 Developers    Fault fault = cpu->read(req, data);
60110037SARM gem5 Developers    memcpy(req->data, &data, sizeof(T));
60210037SARM gem5 Developers
60310037SARM gem5 Developers    ++usedPorts;
60410037SARM gem5 Developers
60510037SARM gem5 Developers    // if we have a cache, do cache access too
60610037SARM gem5 Developers    if (fault == NoFault && dcacheInterface) {
60710037SARM gem5 Developers        if (dcacheInterface->isBlocked()) {
60810037SARM gem5 Developers            // There's an older load that's already going to squash.
60910037SARM gem5 Developers            if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
61010037SARM gem5 Developers                return NoFault;
61110037SARM gem5 Developers
61210037SARM gem5 Developers            isLoadBlocked = true;
61310037SARM gem5 Developers            loadBlockedHandled = false;
61410037SARM gem5 Developers            blockedLoadSeqNum = inst->seqNum;
61510037SARM gem5 Developers            // No fault occurred, even though the interface is blocked.
61610037SARM gem5 Developers            return NoFault;
61711771SCurtis.Dunham@arm.com        }
61810037SARM gem5 Developers        DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
61910037SARM gem5 Developers                loadQueue[load_idx]->readPC());
62010037SARM gem5 Developers/*
62110037SARM gem5 Developers        Addr debug_addr = ULL(0xfffffc0000be81a8);
6227614Sminkyu.jeong@arm.com        if (req->vaddr == debug_addr) {
62310037SARM gem5 Developers            debug_break();
6247614Sminkyu.jeong@arm.com        }
6257614Sminkyu.jeong@arm.com*/
62611771SCurtis.Dunham@arm.com        assert(!req->completionEvent);
62711771SCurtis.Dunham@arm.com        req->completionEvent =
62811771SCurtis.Dunham@arm.com            new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
62911771SCurtis.Dunham@arm.com        MemAccessResult result = dcacheInterface->access(req);
63011771SCurtis.Dunham@arm.com
63111771SCurtis.Dunham@arm.com        assert(dcacheInterface->doEvents());
63211771SCurtis.Dunham@arm.com
63311771SCurtis.Dunham@arm.com        // Ugly hack to get an event scheduled *only* if the access is
63411771SCurtis.Dunham@arm.com        // a miss.  We really should add first-class support for this
63511771SCurtis.Dunham@arm.com        // at some point.
63611771SCurtis.Dunham@arm.com        if (result != MA_HIT) {
63711771SCurtis.Dunham@arm.com            DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
63811771SCurtis.Dunham@arm.com            DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
63911771SCurtis.Dunham@arm.com                    inst->seqNum);
64011771SCurtis.Dunham@arm.com
64111771SCurtis.Dunham@arm.com            lastDcacheStall = curTick;
64211771SCurtis.Dunham@arm.com
64311771SCurtis.Dunham@arm.com//            _status = DcacheMissStall;
64411771SCurtis.Dunham@arm.com
64511771SCurtis.Dunham@arm.com        } else {
64611771SCurtis.Dunham@arm.com            DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
64710905Sandreas.sandberg@arm.com                    inst->seqNum);
6487733SAli.Saidi@ARM.com
6497733SAli.Saidi@ARM.com            DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
65012529Sgiacomo.travaglini@arm.com        }
65110037SARM gem5 Developers    }
65211771SCurtis.Dunham@arm.com#if 0
65310037SARM gem5 Developers    // if we have a cache, do cache access too
65410037SARM gem5 Developers    if (dcacheInterface) {
65510037SARM gem5 Developers        if (dcacheInterface->isBlocked()) {
65610037SARM gem5 Developers            isLoadBlocked = true;
65713114Sgiacomo.travaglini@arm.com            // No fault occurred, even though the interface is blocked.
6587733SAli.Saidi@ARM.com            return NoFault;
65910905Sandreas.sandberg@arm.com        }
6607733SAli.Saidi@ARM.com
6617733SAli.Saidi@ARM.com        DPRINTF(LSQUnit, "LSQUnit: D-cache: PC:%#x reading from paddr:%#x "
66212529Sgiacomo.travaglini@arm.com                "vaddr:%#x flags:%i\n",
6637733SAli.Saidi@ARM.com                inst->readPC(), req->paddr, req->vaddr, req->flags);
6647733SAli.Saidi@ARM.com
66510037SARM gem5 Developers        // Setup MemReq pointer
66611771SCurtis.Dunham@arm.com        req->cmd = Read;
66710037SARM gem5 Developers        req->completionEvent = NULL;
66810037SARM gem5 Developers        req->time = curTick;
66910037SARM gem5 Developers        assert(!req->data);
67010037SARM gem5 Developers        req->data = new uint8_t[64];
67113114Sgiacomo.travaglini@arm.com
6727733SAli.Saidi@ARM.com        assert(!req->completionEvent);
6736313Sgblack@eecs.umich.edu        req->completionEvent =
67412972Sandreas.sandberg@arm.com            new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
6759461Snilay@cs.wisc.edu
67611165SRekai.GonzalezAlberquilla@arm.com        // Do Cache Access
67711165SRekai.GonzalezAlberquilla@arm.com        MemAccessResult result = dcacheInterface->access(req);
67812109SRekai.GonzalezAlberquilla@arm.com
67912109SRekai.GonzalezAlberquilla@arm.com        // Ugly hack to get an event scheduled *only* if the access is
68012109SRekai.GonzalezAlberquilla@arm.com        // a miss.  We really should add first-class support for this
68112109SRekai.GonzalezAlberquilla@arm.com        // at some point.
68212109SRekai.GonzalezAlberquilla@arm.com        // @todo: Probably should support having no events
68312109SRekai.GonzalezAlberquilla@arm.com        if (result != MA_HIT) {
6849553Sandreas.hansson@arm.com            DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
6859553Sandreas.hansson@arm.com            DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
6869553Sandreas.hansson@arm.com                    inst->seqNum);
6879384SAndreas.Sandberg@arm.com
6887400SAli.Saidi@ARM.com            lastDcacheStall = curTick;
6899384SAndreas.Sandberg@arm.com
6909384SAndreas.Sandberg@arm.com            _status = DcacheMissStall;
6919384SAndreas.Sandberg@arm.com
6926313Sgblack@eecs.umich.edu        } else {
6936313Sgblack@eecs.umich.edu            DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
6946313Sgblack@eecs.umich.edu                    inst->seqNum);
69512109SRekai.GonzalezAlberquilla@arm.com
69612109SRekai.GonzalezAlberquilla@arm.com            DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
69712109SRekai.GonzalezAlberquilla@arm.com        }
69812109SRekai.GonzalezAlberquilla@arm.com    } else {
69912109SRekai.GonzalezAlberquilla@arm.com        fatal("Must use D-cache with new memory system");
70012109SRekai.GonzalezAlberquilla@arm.com    }
70112109SRekai.GonzalezAlberquilla@arm.com#endif
70212109SRekai.GonzalezAlberquilla@arm.com
70312109SRekai.GonzalezAlberquilla@arm.com    return fault;
70412109SRekai.GonzalezAlberquilla@arm.com}
70512109SRekai.GonzalezAlberquilla@arm.com
70612109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl>
70712109SRekai.GonzalezAlberquilla@arm.comtemplate <class T>
7086313Sgblack@eecs.umich.eduFault
709LSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx)
710{
711    assert(storeQueue[store_idx].inst);
712
713    DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
714            " | storeHead:%i [sn:%i]\n",
715            store_idx, req->paddr, data, storeHead,
716            storeQueue[store_idx].inst->seqNum);
717/*
718    if (req->flags & LOCKED) {
719        if (req->flags & UNCACHEABLE) {
720            req->result = 2;
721        } else {
722            req->result = 1;
723        }
724    }
725*/
726    storeQueue[store_idx].req = req;
727    storeQueue[store_idx].size = sizeof(T);
728    storeQueue[store_idx].data = data;
729/*
730    Addr debug_addr = ULL(0xfffffc0000be81a8);
731    if (req->vaddr == debug_addr) {
732        debug_break();
733    }
734*/
735    // This function only writes the data to the store queue, so no fault
736    // can happen here.
737    return NoFault;
738}
739
740#endif // __CPU_O3_LSQ_UNIT_HH__
741