lsq_unit.hh revision 5386:5614618f4027
17396Sgblack@eecs.umich.edu/*
27396Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan
37396Sgblack@eecs.umich.edu * All rights reserved.
47396Sgblack@eecs.umich.edu *
57396Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67396Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77396Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97396Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117396Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127396Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137396Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147396Sgblack@eecs.umich.edu * this software without specific prior written permission.
157396Sgblack@eecs.umich.edu *
167396Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177396Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187396Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197396Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207396Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217396Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227396Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237396Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247396Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257396Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267396Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277396Sgblack@eecs.umich.edu *
287396Sgblack@eecs.umich.edu * Authors: Kevin Lim
297396Sgblack@eecs.umich.edu *          Korey Sewell
307396Sgblack@eecs.umich.edu */
317396Sgblack@eecs.umich.edu
327396Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__
337396Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__
347396Sgblack@eecs.umich.edu
357396Sgblack@eecs.umich.edu#include <algorithm>
367396Sgblack@eecs.umich.edu#include <cstring>
377396Sgblack@eecs.umich.edu#include <map>
387396Sgblack@eecs.umich.edu#include <queue>
397396Sgblack@eecs.umich.edu
407396Sgblack@eecs.umich.edu#include "arch/faults.hh"
417396Sgblack@eecs.umich.edu#include "arch/locked_mem.hh"
427434Sgblack@eecs.umich.edu#include "config/full_system.hh"
437434Sgblack@eecs.umich.edu#include "base/fast_alloc.hh"
447434Sgblack@eecs.umich.edu#include "base/hashmap.hh"
457434Sgblack@eecs.umich.edu#include "cpu/inst_seq.hh"
467434Sgblack@eecs.umich.edu#include "mem/packet.hh"
477434Sgblack@eecs.umich.edu#include "mem/port.hh"
487396Sgblack@eecs.umich.edu
497396Sgblack@eecs.umich.edu/**
507396Sgblack@eecs.umich.edu * Class that implements the actual LQ and SQ for each specific
517396Sgblack@eecs.umich.edu * thread.  Both are circular queues; load entries are freed upon
527396Sgblack@eecs.umich.edu * committing, while store entries are freed once they writeback. The
537396Sgblack@eecs.umich.edu * LSQUnit tracks if there are memory ordering violations, and also
547396Sgblack@eecs.umich.edu * detects partial load to store forwarding cases (a store only has
557396Sgblack@eecs.umich.edu * part of a load's data) that requires the load to wait until the
567396Sgblack@eecs.umich.edu * store writes back. In the former case it holds onto the instruction
577396Sgblack@eecs.umich.edu * until the dependence unit looks at it, and in the latter it stalls
587396Sgblack@eecs.umich.edu * the LSQ until the store writes back. At that point the load is
597396Sgblack@eecs.umich.edu * replayed.
607396Sgblack@eecs.umich.edu */
617396Sgblack@eecs.umich.edutemplate <class Impl>
627396Sgblack@eecs.umich.educlass LSQUnit {
637396Sgblack@eecs.umich.edu  protected:
647396Sgblack@eecs.umich.edu    typedef TheISA::IntReg IntReg;
657396Sgblack@eecs.umich.edu  public:
667396Sgblack@eecs.umich.edu    typedef typename Impl::Params Params;
677396Sgblack@eecs.umich.edu    typedef typename Impl::O3CPU O3CPU;
687396Sgblack@eecs.umich.edu    typedef typename Impl::DynInstPtr DynInstPtr;
697396Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::IEW IEW;
707396Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::LSQ LSQ;
717396Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
727396Sgblack@eecs.umich.edu
737396Sgblack@eecs.umich.edu  public:
747396Sgblack@eecs.umich.edu    /** Constructs an LSQ unit. init() must be called prior to use. */
757396Sgblack@eecs.umich.edu    LSQUnit();
767396Sgblack@eecs.umich.edu
777396Sgblack@eecs.umich.edu    /** Initializes the LSQ unit with the specified number of entries. */
787396Sgblack@eecs.umich.edu    void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
797396Sgblack@eecs.umich.edu              unsigned maxLQEntries, unsigned maxSQEntries, unsigned id);
807396Sgblack@eecs.umich.edu
817396Sgblack@eecs.umich.edu    /** Returns the name of the LSQ unit. */
827396Sgblack@eecs.umich.edu    std::string name() const;
837396Sgblack@eecs.umich.edu
847396Sgblack@eecs.umich.edu    /** Registers statistics. */
857396Sgblack@eecs.umich.edu    void regStats();
867396Sgblack@eecs.umich.edu
877396Sgblack@eecs.umich.edu    /** Sets the pointer to the dcache port. */
887396Sgblack@eecs.umich.edu    void setDcachePort(Port *dcache_port);
897396Sgblack@eecs.umich.edu
907396Sgblack@eecs.umich.edu    /** Switches out LSQ unit. */
917396Sgblack@eecs.umich.edu    void switchOut();
927396Sgblack@eecs.umich.edu
937430Sgblack@eecs.umich.edu    /** Takes over from another CPU's thread. */
947430Sgblack@eecs.umich.edu    void takeOverFrom();
957430Sgblack@eecs.umich.edu
967430Sgblack@eecs.umich.edu    /** Returns if the LSQ is switched out. */
977430Sgblack@eecs.umich.edu    bool isSwitchedOut() { return switchedOut; }
987430Sgblack@eecs.umich.edu
997430Sgblack@eecs.umich.edu    /** Ticks the LSQ unit, which in this case only resets the number of
1007430Sgblack@eecs.umich.edu     * used cache ports.
1017430Sgblack@eecs.umich.edu     * @todo: Move the number of used ports up to the LSQ level so it can
1027430Sgblack@eecs.umich.edu     * be shared by all LSQ units.
1037430Sgblack@eecs.umich.edu     */
1047430Sgblack@eecs.umich.edu    void tick() { usedPorts = 0; }
1057430Sgblack@eecs.umich.edu
1067430Sgblack@eecs.umich.edu    /** Inserts an instruction. */
1077430Sgblack@eecs.umich.edu    void insert(DynInstPtr &inst);
1087430Sgblack@eecs.umich.edu    /** Inserts a load instruction. */
1097430Sgblack@eecs.umich.edu    void insertLoad(DynInstPtr &load_inst);
1107430Sgblack@eecs.umich.edu    /** Inserts a store instruction. */
1117430Sgblack@eecs.umich.edu    void insertStore(DynInstPtr &store_inst);
1127430Sgblack@eecs.umich.edu
1137430Sgblack@eecs.umich.edu    /** Executes a load instruction. */
1147430Sgblack@eecs.umich.edu    Fault executeLoad(DynInstPtr &inst);
1157430Sgblack@eecs.umich.edu
1167430Sgblack@eecs.umich.edu    Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
1177430Sgblack@eecs.umich.edu    /** Executes a store instruction. */
1187430Sgblack@eecs.umich.edu    Fault executeStore(DynInstPtr &inst);
1197430Sgblack@eecs.umich.edu
1207430Sgblack@eecs.umich.edu    /** Commits the head load. */
1217430Sgblack@eecs.umich.edu    void commitLoad();
1227430Sgblack@eecs.umich.edu    /** Commits loads older than a specific sequence number. */
1237430Sgblack@eecs.umich.edu    void commitLoads(InstSeqNum &youngest_inst);
1247430Sgblack@eecs.umich.edu
1257430Sgblack@eecs.umich.edu    /** Commits stores older than a specific sequence number. */
1267430Sgblack@eecs.umich.edu    void commitStores(InstSeqNum &youngest_inst);
1277430Sgblack@eecs.umich.edu
1287430Sgblack@eecs.umich.edu    /** Writes back stores. */
1297430Sgblack@eecs.umich.edu    void writebackStores();
1307430Sgblack@eecs.umich.edu
1317430Sgblack@eecs.umich.edu    /** Completes the data access that has been returned from the
1327430Sgblack@eecs.umich.edu     * memory system. */
1337430Sgblack@eecs.umich.edu    void completeDataAccess(PacketPtr pkt);
1347430Sgblack@eecs.umich.edu
1357430Sgblack@eecs.umich.edu    /** Clears all the entries in the LQ. */
1367430Sgblack@eecs.umich.edu    void clearLQ();
1377430Sgblack@eecs.umich.edu
1387430Sgblack@eecs.umich.edu    /** Clears all the entries in the SQ. */
1397430Sgblack@eecs.umich.edu    void clearSQ();
1407430Sgblack@eecs.umich.edu
1417430Sgblack@eecs.umich.edu    /** Resizes the LQ to a given size. */
1427430Sgblack@eecs.umich.edu    void resizeLQ(unsigned size);
1437430Sgblack@eecs.umich.edu
1447430Sgblack@eecs.umich.edu    /** Resizes the SQ to a given size. */
1457430Sgblack@eecs.umich.edu    void resizeSQ(unsigned size);
1467430Sgblack@eecs.umich.edu
1477430Sgblack@eecs.umich.edu    /** Squashes all instructions younger than a specific sequence number. */
1487430Sgblack@eecs.umich.edu    void squash(const InstSeqNum &squashed_num);
1497430Sgblack@eecs.umich.edu
1507430Sgblack@eecs.umich.edu    /** Returns if there is a memory ordering violation. Value is reset upon
1517430Sgblack@eecs.umich.edu     * call to getMemDepViolator().
1527430Sgblack@eecs.umich.edu     */
1537430Sgblack@eecs.umich.edu    bool violation() { return memDepViolator; }
1547430Sgblack@eecs.umich.edu
1557430Sgblack@eecs.umich.edu    /** Returns the memory ordering violator. */
1567430Sgblack@eecs.umich.edu    DynInstPtr getMemDepViolator();
1577430Sgblack@eecs.umich.edu
1587430Sgblack@eecs.umich.edu    /** Returns if a load became blocked due to the memory system. */
1597430Sgblack@eecs.umich.edu    bool loadBlocked()
1607430Sgblack@eecs.umich.edu    { return isLoadBlocked; }
1617430Sgblack@eecs.umich.edu
1627430Sgblack@eecs.umich.edu    /** Clears the signal that a load became blocked. */
1637430Sgblack@eecs.umich.edu    void clearLoadBlocked()
1647430Sgblack@eecs.umich.edu    { isLoadBlocked = false; }
1657430Sgblack@eecs.umich.edu
1667430Sgblack@eecs.umich.edu    /** Returns if the blocked load was handled. */
1677430Sgblack@eecs.umich.edu    bool isLoadBlockedHandled()
1687430Sgblack@eecs.umich.edu    { return loadBlockedHandled; }
1697430Sgblack@eecs.umich.edu
1707430Sgblack@eecs.umich.edu    /** Records the blocked load as being handled. */
1717430Sgblack@eecs.umich.edu    void setLoadBlockedHandled()
1727430Sgblack@eecs.umich.edu    { loadBlockedHandled = true; }
1737430Sgblack@eecs.umich.edu
1747430Sgblack@eecs.umich.edu    /** Returns the number of free entries (min of free LQ and SQ entries). */
1757430Sgblack@eecs.umich.edu    unsigned numFreeEntries();
1767430Sgblack@eecs.umich.edu
1777430Sgblack@eecs.umich.edu    /** Returns the number of loads ready to execute. */
1787430Sgblack@eecs.umich.edu    int numLoadsReady();
1797430Sgblack@eecs.umich.edu
1807430Sgblack@eecs.umich.edu    /** Returns the number of loads in the LQ. */
1817430Sgblack@eecs.umich.edu    int numLoads() { return loads; }
1827430Sgblack@eecs.umich.edu
1837430Sgblack@eecs.umich.edu    /** Returns the number of stores in the SQ. */
1847430Sgblack@eecs.umich.edu    int numStores() { return stores; }
1857430Sgblack@eecs.umich.edu
1867430Sgblack@eecs.umich.edu    /** Returns if either the LQ or SQ is full. */
1877430Sgblack@eecs.umich.edu    bool isFull() { return lqFull() || sqFull(); }
1887430Sgblack@eecs.umich.edu
1897430Sgblack@eecs.umich.edu    /** Returns if the LQ is full. */
1907430Sgblack@eecs.umich.edu    bool lqFull() { return loads >= (LQEntries - 1); }
1917430Sgblack@eecs.umich.edu
1927430Sgblack@eecs.umich.edu    /** Returns if the SQ is full. */
1937430Sgblack@eecs.umich.edu    bool sqFull() { return stores >= (SQEntries - 1); }
1947430Sgblack@eecs.umich.edu
1957430Sgblack@eecs.umich.edu    /** Returns the number of instructions in the LSQ. */
1967430Sgblack@eecs.umich.edu    unsigned getCount() { return loads + stores; }
1977430Sgblack@eecs.umich.edu
1987430Sgblack@eecs.umich.edu    /** Returns if there are any stores to writeback. */
1997430Sgblack@eecs.umich.edu    bool hasStoresToWB() { return storesToWB; }
2007430Sgblack@eecs.umich.edu
2017430Sgblack@eecs.umich.edu    /** Returns the number of stores to writeback. */
2027430Sgblack@eecs.umich.edu    int numStoresToWB() { return storesToWB; }
2037430Sgblack@eecs.umich.edu
2047430Sgblack@eecs.umich.edu    /** Returns if the LSQ unit will writeback on this cycle. */
2057430Sgblack@eecs.umich.edu    bool willWB() { return storeQueue[storeWBIdx].canWB &&
2067430Sgblack@eecs.umich.edu                        !storeQueue[storeWBIdx].completed &&
2077430Sgblack@eecs.umich.edu                        !isStoreBlocked; }
2087430Sgblack@eecs.umich.edu
2097430Sgblack@eecs.umich.edu    /** Handles doing the retry. */
2107430Sgblack@eecs.umich.edu    void recvRetry();
2117430Sgblack@eecs.umich.edu
2127430Sgblack@eecs.umich.edu  private:
2137430Sgblack@eecs.umich.edu    /** Writes back the instruction, sending it to IEW. */
2147430Sgblack@eecs.umich.edu    void writeback(DynInstPtr &inst, PacketPtr pkt);
2157430Sgblack@eecs.umich.edu
2167430Sgblack@eecs.umich.edu    /** Handles completing the send of a store to memory. */
2177430Sgblack@eecs.umich.edu    void storePostSend(PacketPtr pkt);
2187430Sgblack@eecs.umich.edu
2197430Sgblack@eecs.umich.edu    /** Completes the store at the specified index. */
2207430Sgblack@eecs.umich.edu    void completeStore(int store_idx);
2217430Sgblack@eecs.umich.edu
2227430Sgblack@eecs.umich.edu    /** Increments the given store index (circular queue). */
2237430Sgblack@eecs.umich.edu    inline void incrStIdx(int &store_idx);
2247430Sgblack@eecs.umich.edu    /** Decrements the given store index (circular queue). */
2257430Sgblack@eecs.umich.edu    inline void decrStIdx(int &store_idx);
2267430Sgblack@eecs.umich.edu    /** Increments the given load index (circular queue). */
2277430Sgblack@eecs.umich.edu    inline void incrLdIdx(int &load_idx);
2287430Sgblack@eecs.umich.edu    /** Decrements the given load index (circular queue). */
2297430Sgblack@eecs.umich.edu    inline void decrLdIdx(int &load_idx);
2307430Sgblack@eecs.umich.edu
2317430Sgblack@eecs.umich.edu  public:
2327430Sgblack@eecs.umich.edu    /** Debugging function to dump instructions in the LSQ. */
2337430Sgblack@eecs.umich.edu    void dumpInsts();
2347430Sgblack@eecs.umich.edu
2357430Sgblack@eecs.umich.edu  private:
2367430Sgblack@eecs.umich.edu    /** Pointer to the CPU. */
2377430Sgblack@eecs.umich.edu    O3CPU *cpu;
2387430Sgblack@eecs.umich.edu
2397430Sgblack@eecs.umich.edu    /** Pointer to the IEW stage. */
2407430Sgblack@eecs.umich.edu    IEW *iewStage;
2417430Sgblack@eecs.umich.edu
2427430Sgblack@eecs.umich.edu    /** Pointer to the LSQ. */
2437430Sgblack@eecs.umich.edu    LSQ *lsq;
2447430Sgblack@eecs.umich.edu
2457430Sgblack@eecs.umich.edu    /** Pointer to the dcache port.  Used only for sending. */
2467430Sgblack@eecs.umich.edu    Port *dcachePort;
2477430Sgblack@eecs.umich.edu
2487430Sgblack@eecs.umich.edu    /** Derived class to hold any sender state the LSQ needs. */
2497430Sgblack@eecs.umich.edu    class LSQSenderState : public Packet::SenderState, public FastAlloc
2507430Sgblack@eecs.umich.edu    {
2517430Sgblack@eecs.umich.edu      public:
2527430Sgblack@eecs.umich.edu        /** Default constructor. */
2537430Sgblack@eecs.umich.edu        LSQSenderState()
2547430Sgblack@eecs.umich.edu            : noWB(false)
2557430Sgblack@eecs.umich.edu        { }
2567430Sgblack@eecs.umich.edu
2577430Sgblack@eecs.umich.edu        /** Instruction who initiated the access to memory. */
2587430Sgblack@eecs.umich.edu        DynInstPtr inst;
2597430Sgblack@eecs.umich.edu        /** Whether or not it is a load. */
2607430Sgblack@eecs.umich.edu        bool isLoad;
2617430Sgblack@eecs.umich.edu        /** The LQ/SQ index of the instruction. */
2627430Sgblack@eecs.umich.edu        int idx;
2637430Sgblack@eecs.umich.edu        /** Whether or not the instruction will need to writeback. */
2647430Sgblack@eecs.umich.edu        bool noWB;
2657430Sgblack@eecs.umich.edu    };
2667430Sgblack@eecs.umich.edu
2677430Sgblack@eecs.umich.edu    /** Writeback event, specifically for when stores forward data to loads. */
2687430Sgblack@eecs.umich.edu    class WritebackEvent : public Event {
2697430Sgblack@eecs.umich.edu      public:
2707430Sgblack@eecs.umich.edu        /** Constructs a writeback event. */
2717430Sgblack@eecs.umich.edu        WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr);
2727430Sgblack@eecs.umich.edu
2737430Sgblack@eecs.umich.edu        /** Processes the writeback event. */
2747430Sgblack@eecs.umich.edu        void process();
2757430Sgblack@eecs.umich.edu
2767430Sgblack@eecs.umich.edu        /** Returns the description of this event. */
2777430Sgblack@eecs.umich.edu        const char *description() const;
2787430Sgblack@eecs.umich.edu
2797430Sgblack@eecs.umich.edu      private:
2807430Sgblack@eecs.umich.edu        /** Instruction whose results are being written back. */
2817430Sgblack@eecs.umich.edu        DynInstPtr inst;
2827430Sgblack@eecs.umich.edu
2837430Sgblack@eecs.umich.edu        /** The packet that would have been sent to memory. */
2847430Sgblack@eecs.umich.edu        PacketPtr pkt;
2857430Sgblack@eecs.umich.edu
2867430Sgblack@eecs.umich.edu        /** The pointer to the LSQ unit that issued the store. */
2877430Sgblack@eecs.umich.edu        LSQUnit<Impl> *lsqPtr;
2887430Sgblack@eecs.umich.edu    };
2897430Sgblack@eecs.umich.edu
2907430Sgblack@eecs.umich.edu  public:
2917430Sgblack@eecs.umich.edu    struct SQEntry {
2927430Sgblack@eecs.umich.edu        /** Constructs an empty store queue entry. */
2937430Sgblack@eecs.umich.edu        SQEntry()
2947430Sgblack@eecs.umich.edu            : inst(NULL), req(NULL), size(0),
2957430Sgblack@eecs.umich.edu              canWB(0), committed(0), completed(0)
2967430Sgblack@eecs.umich.edu        {
2977430Sgblack@eecs.umich.edu            std::memset(data, 0, sizeof(data));
2987430Sgblack@eecs.umich.edu        }
2997430Sgblack@eecs.umich.edu
3007430Sgblack@eecs.umich.edu        /** Constructs a store queue entry for a given instruction. */
3017430Sgblack@eecs.umich.edu        SQEntry(DynInstPtr &_inst)
3027430Sgblack@eecs.umich.edu            : inst(_inst), req(NULL), size(0),
3037430Sgblack@eecs.umich.edu              canWB(0), committed(0), completed(0)
3047430Sgblack@eecs.umich.edu        {
3057430Sgblack@eecs.umich.edu            std::memset(data, 0, sizeof(data));
3067430Sgblack@eecs.umich.edu        }
3077430Sgblack@eecs.umich.edu
3087430Sgblack@eecs.umich.edu        /** The store instruction. */
3097430Sgblack@eecs.umich.edu        DynInstPtr inst;
3107430Sgblack@eecs.umich.edu        /** The request for the store. */
3117430Sgblack@eecs.umich.edu        RequestPtr req;
3127430Sgblack@eecs.umich.edu        /** The size of the store. */
3137430Sgblack@eecs.umich.edu        int size;
3147430Sgblack@eecs.umich.edu        /** The store data. */
3157430Sgblack@eecs.umich.edu        char data[sizeof(IntReg)];
3167430Sgblack@eecs.umich.edu        /** Whether or not the store can writeback. */
3177430Sgblack@eecs.umich.edu        bool canWB;
3187430Sgblack@eecs.umich.edu        /** Whether or not the store is committed. */
3197430Sgblack@eecs.umich.edu        bool committed;
3207430Sgblack@eecs.umich.edu        /** Whether or not the store is completed. */
3217430Sgblack@eecs.umich.edu        bool completed;
3227430Sgblack@eecs.umich.edu    };
3237430Sgblack@eecs.umich.edu
3247430Sgblack@eecs.umich.edu  private:
3257430Sgblack@eecs.umich.edu    /** The LSQUnit thread id. */
3267430Sgblack@eecs.umich.edu    unsigned lsqID;
3277430Sgblack@eecs.umich.edu
3287430Sgblack@eecs.umich.edu    /** The store queue. */
3297430Sgblack@eecs.umich.edu    std::vector<SQEntry> storeQueue;
3307430Sgblack@eecs.umich.edu
3317430Sgblack@eecs.umich.edu    /** The load queue. */
3327430Sgblack@eecs.umich.edu    std::vector<DynInstPtr> loadQueue;
3337430Sgblack@eecs.umich.edu
3347430Sgblack@eecs.umich.edu    /** The number of LQ entries, plus a sentinel entry (circular queue).
3357430Sgblack@eecs.umich.edu     *  @todo: Consider having var that records the true number of LQ entries.
3367430Sgblack@eecs.umich.edu     */
3377430Sgblack@eecs.umich.edu    unsigned LQEntries;
3387430Sgblack@eecs.umich.edu    /** The number of SQ entries, plus a sentinel entry (circular queue).
3397430Sgblack@eecs.umich.edu     *  @todo: Consider having var that records the true number of SQ entries.
3407430Sgblack@eecs.umich.edu     */
3417430Sgblack@eecs.umich.edu    unsigned SQEntries;
3427430Sgblack@eecs.umich.edu
3437430Sgblack@eecs.umich.edu    /** The number of load instructions in the LQ. */
3447430Sgblack@eecs.umich.edu    int loads;
3457430Sgblack@eecs.umich.edu    /** The number of store instructions in the SQ. */
3467430Sgblack@eecs.umich.edu    int stores;
3477430Sgblack@eecs.umich.edu    /** The number of store instructions in the SQ waiting to writeback. */
3487430Sgblack@eecs.umich.edu    int storesToWB;
3497430Sgblack@eecs.umich.edu
3507430Sgblack@eecs.umich.edu    /** The index of the head instruction in the LQ. */
3517430Sgblack@eecs.umich.edu    int loadHead;
3527430Sgblack@eecs.umich.edu    /** The index of the tail instruction in the LQ. */
3537430Sgblack@eecs.umich.edu    int loadTail;
3547430Sgblack@eecs.umich.edu
3557430Sgblack@eecs.umich.edu    /** The index of the head instruction in the SQ. */
3567430Sgblack@eecs.umich.edu    int storeHead;
3577430Sgblack@eecs.umich.edu    /** The index of the first instruction that may be ready to be
3587430Sgblack@eecs.umich.edu     * written back, and has not yet been written back.
3597430Sgblack@eecs.umich.edu     */
3607430Sgblack@eecs.umich.edu    int storeWBIdx;
3617430Sgblack@eecs.umich.edu    /** The index of the tail instruction in the SQ. */
3627430Sgblack@eecs.umich.edu    int storeTail;
3637430Sgblack@eecs.umich.edu
3647430Sgblack@eecs.umich.edu    /// @todo Consider moving to a more advanced model with write vs read ports
3657430Sgblack@eecs.umich.edu    /** The number of cache ports available each cycle. */
3667430Sgblack@eecs.umich.edu    int cachePorts;
3677430Sgblack@eecs.umich.edu
3687430Sgblack@eecs.umich.edu    /** The number of used cache ports in this cycle. */
3697430Sgblack@eecs.umich.edu    int usedPorts;
3707430Sgblack@eecs.umich.edu
3717430Sgblack@eecs.umich.edu    /** Is the LSQ switched out. */
3727430Sgblack@eecs.umich.edu    bool switchedOut;
3737430Sgblack@eecs.umich.edu
3747430Sgblack@eecs.umich.edu    //list<InstSeqNum> mshrSeqNums;
3757430Sgblack@eecs.umich.edu
3767430Sgblack@eecs.umich.edu    /** Wire to read information from the issue stage time queue. */
3777430Sgblack@eecs.umich.edu    typename TimeBuffer<IssueStruct>::wire fromIssue;
3787430Sgblack@eecs.umich.edu
3797430Sgblack@eecs.umich.edu    /** Whether or not the LSQ is stalled. */
3807430Sgblack@eecs.umich.edu    bool stalled;
3817430Sgblack@eecs.umich.edu    /** The store that causes the stall due to partial store to load
3827430Sgblack@eecs.umich.edu     * forwarding.
3837430Sgblack@eecs.umich.edu     */
3847430Sgblack@eecs.umich.edu    InstSeqNum stallingStoreIsn;
3857430Sgblack@eecs.umich.edu    /** The index of the above store. */
3867430Sgblack@eecs.umich.edu    int stallingLoadIdx;
3877430Sgblack@eecs.umich.edu
3887430Sgblack@eecs.umich.edu    /** The packet that needs to be retried. */
3897430Sgblack@eecs.umich.edu    PacketPtr retryPkt;
3907430Sgblack@eecs.umich.edu
3917430Sgblack@eecs.umich.edu    /** Whehter or not a store is blocked due to the memory system. */
3927430Sgblack@eecs.umich.edu    bool isStoreBlocked;
3937430Sgblack@eecs.umich.edu
3947430Sgblack@eecs.umich.edu    /** Whether or not a load is blocked due to the memory system. */
3957430Sgblack@eecs.umich.edu    bool isLoadBlocked;
3967430Sgblack@eecs.umich.edu
3977430Sgblack@eecs.umich.edu    /** Has the blocked load been handled. */
3987430Sgblack@eecs.umich.edu    bool loadBlockedHandled;
3997430Sgblack@eecs.umich.edu
4007430Sgblack@eecs.umich.edu    /** The sequence number of the blocked load. */
4017430Sgblack@eecs.umich.edu    InstSeqNum blockedLoadSeqNum;
4027430Sgblack@eecs.umich.edu
4037430Sgblack@eecs.umich.edu    /** The oldest load that caused a memory ordering violation. */
4047430Sgblack@eecs.umich.edu    DynInstPtr memDepViolator;
4057430Sgblack@eecs.umich.edu
4067430Sgblack@eecs.umich.edu    // Will also need how many read/write ports the Dcache has.  Or keep track
4077430Sgblack@eecs.umich.edu    // of that in stage that is one level up, and only call executeLoad/Store
4087430Sgblack@eecs.umich.edu    // the appropriate number of times.
4097430Sgblack@eecs.umich.edu    /** Total number of loads forwaded from LSQ stores. */
4107430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqForwLoads;
4117430Sgblack@eecs.umich.edu
4127430Sgblack@eecs.umich.edu    /** Total number of loads ignored due to invalid addresses. */
4137430Sgblack@eecs.umich.edu    Stats::Scalar<> invAddrLoads;
4147430Sgblack@eecs.umich.edu
4157430Sgblack@eecs.umich.edu    /** Total number of squashed loads. */
4167430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqSquashedLoads;
4177430Sgblack@eecs.umich.edu
4187430Sgblack@eecs.umich.edu    /** Total number of responses from the memory system that are
4197430Sgblack@eecs.umich.edu     * ignored due to the instruction already being squashed. */
4207430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqIgnoredResponses;
4217430Sgblack@eecs.umich.edu
4227430Sgblack@eecs.umich.edu    /** Tota number of memory ordering violations. */
4237430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqMemOrderViolation;
4247430Sgblack@eecs.umich.edu
4257430Sgblack@eecs.umich.edu    /** Total number of squashed stores. */
4267430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqSquashedStores;
4277430Sgblack@eecs.umich.edu
4287430Sgblack@eecs.umich.edu    /** Total number of software prefetches ignored due to invalid addresses. */
4297430Sgblack@eecs.umich.edu    Stats::Scalar<> invAddrSwpfs;
4307430Sgblack@eecs.umich.edu
4317430Sgblack@eecs.umich.edu    /** Ready loads blocked due to partial store-forwarding. */
4327430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqBlockedLoads;
4337430Sgblack@eecs.umich.edu
4347430Sgblack@eecs.umich.edu    /** Number of loads that were rescheduled. */
4357430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqRescheduledLoads;
4367430Sgblack@eecs.umich.edu
4377430Sgblack@eecs.umich.edu    /** Number of times the LSQ is blocked due to the cache. */
4387430Sgblack@eecs.umich.edu    Stats::Scalar<> lsqCacheBlocked;
4397430Sgblack@eecs.umich.edu
4407430Sgblack@eecs.umich.edu  public:
4417430Sgblack@eecs.umich.edu    /** Executes the load at the given index. */
4427430Sgblack@eecs.umich.edu    template <class T>
4437430Sgblack@eecs.umich.edu    Fault read(Request *req, T &data, int load_idx);
4447430Sgblack@eecs.umich.edu
4457430Sgblack@eecs.umich.edu    /** Executes the store at the given index. */
4467430Sgblack@eecs.umich.edu    template <class T>
4477430Sgblack@eecs.umich.edu    Fault write(Request *req, T &data, int store_idx);
4487430Sgblack@eecs.umich.edu
4497430Sgblack@eecs.umich.edu    /** Returns the index of the head load instruction. */
4507430Sgblack@eecs.umich.edu    int getLoadHead() { return loadHead; }
4517430Sgblack@eecs.umich.edu    /** Returns the sequence number of the head load instruction. */
4527430Sgblack@eecs.umich.edu    InstSeqNum getLoadHeadSeqNum()
4537430Sgblack@eecs.umich.edu    {
4547430Sgblack@eecs.umich.edu        if (loadQueue[loadHead]) {
4557430Sgblack@eecs.umich.edu            return loadQueue[loadHead]->seqNum;
4567430Sgblack@eecs.umich.edu        } else {
4577430Sgblack@eecs.umich.edu            return 0;
4587430Sgblack@eecs.umich.edu        }
4597430Sgblack@eecs.umich.edu
4607430Sgblack@eecs.umich.edu    }
4617430Sgblack@eecs.umich.edu
4627430Sgblack@eecs.umich.edu    /** Returns the index of the head store instruction. */
4637430Sgblack@eecs.umich.edu    int getStoreHead() { return storeHead; }
4647430Sgblack@eecs.umich.edu    /** Returns the sequence number of the head store instruction. */
4657430Sgblack@eecs.umich.edu    InstSeqNum getStoreHeadSeqNum()
4667430Sgblack@eecs.umich.edu    {
4677430Sgblack@eecs.umich.edu        if (storeQueue[storeHead].inst) {
4687430Sgblack@eecs.umich.edu            return storeQueue[storeHead].inst->seqNum;
4697430Sgblack@eecs.umich.edu        } else {
4707430Sgblack@eecs.umich.edu            return 0;
4717430Sgblack@eecs.umich.edu        }
4727430Sgblack@eecs.umich.edu
4737430Sgblack@eecs.umich.edu    }
4747430Sgblack@eecs.umich.edu
4757430Sgblack@eecs.umich.edu    /** Returns whether or not the LSQ unit is stalled. */
4767430Sgblack@eecs.umich.edu    bool isStalled()  { return stalled; }
4777430Sgblack@eecs.umich.edu};
4787430Sgblack@eecs.umich.edu
4797430Sgblack@eecs.umich.edutemplate <class Impl>
4807430Sgblack@eecs.umich.edutemplate <class T>
4817430Sgblack@eecs.umich.eduFault
4827430Sgblack@eecs.umich.eduLSQUnit<Impl>::read(Request *req, T &data, int load_idx)
4837430Sgblack@eecs.umich.edu{
4847430Sgblack@eecs.umich.edu    DynInstPtr load_inst = loadQueue[load_idx];
4857430Sgblack@eecs.umich.edu
4867430Sgblack@eecs.umich.edu    assert(load_inst);
4877430Sgblack@eecs.umich.edu
4887430Sgblack@eecs.umich.edu    assert(!load_inst->isExecuted());
4897430Sgblack@eecs.umich.edu
4907430Sgblack@eecs.umich.edu    // Make sure this isn't an uncacheable access
4917430Sgblack@eecs.umich.edu    // A bit of a hackish way to get uncached accesses to work only if they're
4927430Sgblack@eecs.umich.edu    // at the head of the LSQ and are ready to commit (at the head of the ROB
4937430Sgblack@eecs.umich.edu    // too).
4947430Sgblack@eecs.umich.edu    if (req->isUncacheable() &&
4957430Sgblack@eecs.umich.edu        (load_idx != loadHead || !load_inst->isAtCommit())) {
4967430Sgblack@eecs.umich.edu        iewStage->rescheduleMemInst(load_inst);
4977430Sgblack@eecs.umich.edu        ++lsqRescheduledLoads;
4987430Sgblack@eecs.umich.edu
4997430Sgblack@eecs.umich.edu        // Must delete request now that it wasn't handed off to
5007430Sgblack@eecs.umich.edu        // memory.  This is quite ugly.  @todo: Figure out the proper
5017430Sgblack@eecs.umich.edu        // place to really handle request deletes.
5027430Sgblack@eecs.umich.edu        delete req;
5037430Sgblack@eecs.umich.edu        return TheISA::genMachineCheckFault();
5047430Sgblack@eecs.umich.edu    }
5057430Sgblack@eecs.umich.edu
5067430Sgblack@eecs.umich.edu    // Check the SQ for any previous stores that might lead to forwarding
5077430Sgblack@eecs.umich.edu    int store_idx = load_inst->sqIdx;
5087430Sgblack@eecs.umich.edu
5097430Sgblack@eecs.umich.edu    int store_size = 0;
5107430Sgblack@eecs.umich.edu
5117430Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
5127430Sgblack@eecs.umich.edu            "storeHead: %i addr: %#x\n",
5137430Sgblack@eecs.umich.edu            load_idx, store_idx, storeHead, req->getPaddr());
5147430Sgblack@eecs.umich.edu
5157430Sgblack@eecs.umich.edu    if (req->isLocked()) {
5167430Sgblack@eecs.umich.edu        // Disable recording the result temporarily.  Writing to misc
5177430Sgblack@eecs.umich.edu        // regs normally updates the result, but this is not the
5187430Sgblack@eecs.umich.edu        // desired behavior when handling store conditionals.
5197430Sgblack@eecs.umich.edu        load_inst->recordResult = false;
5207430Sgblack@eecs.umich.edu        TheISA::handleLockedRead(load_inst.get(), req);
5217430Sgblack@eecs.umich.edu        load_inst->recordResult = true;
5227430Sgblack@eecs.umich.edu    }
5237430Sgblack@eecs.umich.edu
5247430Sgblack@eecs.umich.edu    while (store_idx != -1) {
5257430Sgblack@eecs.umich.edu        // End once we've reached the top of the LSQ
5267430Sgblack@eecs.umich.edu        if (store_idx == storeWBIdx) {
5277430Sgblack@eecs.umich.edu            break;
5287430Sgblack@eecs.umich.edu        }
5297430Sgblack@eecs.umich.edu
5307430Sgblack@eecs.umich.edu        // Move the index to one younger
5317430Sgblack@eecs.umich.edu        if (--store_idx < 0)
5327430Sgblack@eecs.umich.edu            store_idx += SQEntries;
5337430Sgblack@eecs.umich.edu
5347430Sgblack@eecs.umich.edu        assert(storeQueue[store_idx].inst);
5357430Sgblack@eecs.umich.edu
5367430Sgblack@eecs.umich.edu        store_size = storeQueue[store_idx].size;
5377430Sgblack@eecs.umich.edu
5387430Sgblack@eecs.umich.edu        if (store_size == 0)
5397430Sgblack@eecs.umich.edu            continue;
5407430Sgblack@eecs.umich.edu        else if (storeQueue[store_idx].inst->uncacheable())
5417430Sgblack@eecs.umich.edu            continue;
5427430Sgblack@eecs.umich.edu
5437430Sgblack@eecs.umich.edu        assert(storeQueue[store_idx].inst->effAddrValid);
5447430Sgblack@eecs.umich.edu
5457430Sgblack@eecs.umich.edu        // Check if the store data is within the lower and upper bounds of
5467430Sgblack@eecs.umich.edu        // addresses that the request needs.
5477430Sgblack@eecs.umich.edu        bool store_has_lower_limit =
5487430Sgblack@eecs.umich.edu            req->getVaddr() >= storeQueue[store_idx].inst->effAddr;
5497430Sgblack@eecs.umich.edu        bool store_has_upper_limit =
5507430Sgblack@eecs.umich.edu            (req->getVaddr() + req->getSize()) <=
5517430Sgblack@eecs.umich.edu            (storeQueue[store_idx].inst->effAddr + store_size);
5527430Sgblack@eecs.umich.edu        bool lower_load_has_store_part =
5537430Sgblack@eecs.umich.edu            req->getVaddr() < (storeQueue[store_idx].inst->effAddr +
5547430Sgblack@eecs.umich.edu                           store_size);
5557430Sgblack@eecs.umich.edu        bool upper_load_has_store_part =
5567430Sgblack@eecs.umich.edu            (req->getVaddr() + req->getSize()) >
5577430Sgblack@eecs.umich.edu            storeQueue[store_idx].inst->effAddr;
5587430Sgblack@eecs.umich.edu
5597430Sgblack@eecs.umich.edu        // If the store's data has all of the data needed, we can forward.
5607430Sgblack@eecs.umich.edu        if ((store_has_lower_limit && store_has_upper_limit)) {
5617430Sgblack@eecs.umich.edu            // Get shift amount for offset into the store's data.
5627430Sgblack@eecs.umich.edu            int shift_amt = req->getVaddr() & (store_size - 1);
5637430Sgblack@eecs.umich.edu
5647430Sgblack@eecs.umich.edu            memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
5657430Sgblack@eecs.umich.edu
5667430Sgblack@eecs.umich.edu            assert(!load_inst->memData);
5677430Sgblack@eecs.umich.edu            load_inst->memData = new uint8_t[64];
5687430Sgblack@eecs.umich.edu
5697430Sgblack@eecs.umich.edu            memcpy(load_inst->memData,
5707430Sgblack@eecs.umich.edu                    storeQueue[store_idx].data + shift_amt, req->getSize());
5717430Sgblack@eecs.umich.edu
5727430Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
5737430Sgblack@eecs.umich.edu                    "addr %#x, data %#x\n",
5747430Sgblack@eecs.umich.edu                    store_idx, req->getVaddr(), data);
5757430Sgblack@eecs.umich.edu
5767430Sgblack@eecs.umich.edu            PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq,
5777430Sgblack@eecs.umich.edu                                            Packet::Broadcast);
5787430Sgblack@eecs.umich.edu            data_pkt->dataStatic(load_inst->memData);
5797430Sgblack@eecs.umich.edu
5807430Sgblack@eecs.umich.edu            WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this);
5817430Sgblack@eecs.umich.edu
5827430Sgblack@eecs.umich.edu            // We'll say this has a 1 cycle load-store forwarding latency
5837430Sgblack@eecs.umich.edu            // for now.
5847430Sgblack@eecs.umich.edu            // @todo: Need to make this a parameter.
5857430Sgblack@eecs.umich.edu            wb->schedule(curTick);
5867430Sgblack@eecs.umich.edu
5877430Sgblack@eecs.umich.edu            ++lsqForwLoads;
5887430Sgblack@eecs.umich.edu            return NoFault;
5897430Sgblack@eecs.umich.edu        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
5907430Sgblack@eecs.umich.edu                   (store_has_upper_limit && upper_load_has_store_part) ||
5917430Sgblack@eecs.umich.edu                   (lower_load_has_store_part && upper_load_has_store_part)) {
5927430Sgblack@eecs.umich.edu            // This is the partial store-load forwarding case where a store
5937430Sgblack@eecs.umich.edu            // has only part of the load's data.
5947430Sgblack@eecs.umich.edu
5957430Sgblack@eecs.umich.edu            // If it's already been written back, then don't worry about
5967430Sgblack@eecs.umich.edu            // stalling on it.
5977430Sgblack@eecs.umich.edu            if (storeQueue[store_idx].completed) {
5987430Sgblack@eecs.umich.edu                panic("Should not check one of these");
5997430Sgblack@eecs.umich.edu                continue;
6007430Sgblack@eecs.umich.edu            }
6017430Sgblack@eecs.umich.edu
6027430Sgblack@eecs.umich.edu            // Must stall load and force it to retry, so long as it's the oldest
6037430Sgblack@eecs.umich.edu            // load that needs to do so.
6047430Sgblack@eecs.umich.edu            if (!stalled ||
6057430Sgblack@eecs.umich.edu                (stalled &&
6067430Sgblack@eecs.umich.edu                 load_inst->seqNum <
6077430Sgblack@eecs.umich.edu                 loadQueue[stallingLoadIdx]->seqNum)) {
6087430Sgblack@eecs.umich.edu                stalled = true;
6097430Sgblack@eecs.umich.edu                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
6107430Sgblack@eecs.umich.edu                stallingLoadIdx = load_idx;
6117430Sgblack@eecs.umich.edu            }
6127430Sgblack@eecs.umich.edu
6137430Sgblack@eecs.umich.edu            // Tell IQ/mem dep unit that this instruction will need to be
6147430Sgblack@eecs.umich.edu            // rescheduled eventually
6157430Sgblack@eecs.umich.edu            iewStage->rescheduleMemInst(load_inst);
6167430Sgblack@eecs.umich.edu            iewStage->decrWb(load_inst->seqNum);
6177430Sgblack@eecs.umich.edu            load_inst->clearIssued();
6187430Sgblack@eecs.umich.edu            ++lsqRescheduledLoads;
6197430Sgblack@eecs.umich.edu
6207430Sgblack@eecs.umich.edu            // Do not generate a writeback event as this instruction is not
6217430Sgblack@eecs.umich.edu            // complete.
6227430Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
6237430Sgblack@eecs.umich.edu                    "Store idx %i to load addr %#x\n",
6247430Sgblack@eecs.umich.edu                    store_idx, req->getVaddr());
6257430Sgblack@eecs.umich.edu
6267430Sgblack@eecs.umich.edu            // Must delete request now that it wasn't handed off to
6277430Sgblack@eecs.umich.edu            // memory.  This is quite ugly.  @todo: Figure out the
6287430Sgblack@eecs.umich.edu            // proper place to really handle request deletes.
6297430Sgblack@eecs.umich.edu            delete req;
6307430Sgblack@eecs.umich.edu
6317430Sgblack@eecs.umich.edu            return NoFault;
6327430Sgblack@eecs.umich.edu        }
6337430Sgblack@eecs.umich.edu    }
6347430Sgblack@eecs.umich.edu
6357430Sgblack@eecs.umich.edu    // If there's no forwarding case, then go access memory
6367430Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
6377430Sgblack@eecs.umich.edu            load_inst->seqNum, load_inst->readPC());
6387430Sgblack@eecs.umich.edu
6397430Sgblack@eecs.umich.edu    assert(!load_inst->memData);
6407430Sgblack@eecs.umich.edu    load_inst->memData = new uint8_t[64];
6417430Sgblack@eecs.umich.edu
6427430Sgblack@eecs.umich.edu    ++usedPorts;
6437430Sgblack@eecs.umich.edu
6447430Sgblack@eecs.umich.edu    // if we the cache is not blocked, do cache access
6457430Sgblack@eecs.umich.edu    if (!lsq->cacheBlocked()) {
6467430Sgblack@eecs.umich.edu        PacketPtr data_pkt =
6477430Sgblack@eecs.umich.edu            new Packet(req,
6487430Sgblack@eecs.umich.edu                       (req->isLocked() ?
6497430Sgblack@eecs.umich.edu                        MemCmd::LoadLockedReq : MemCmd::ReadReq),
6507430Sgblack@eecs.umich.edu                       Packet::Broadcast);
6517430Sgblack@eecs.umich.edu        data_pkt->dataStatic(load_inst->memData);
6527430Sgblack@eecs.umich.edu
6537430Sgblack@eecs.umich.edu        LSQSenderState *state = new LSQSenderState;
6547430Sgblack@eecs.umich.edu        state->isLoad = true;
6557430Sgblack@eecs.umich.edu        state->idx = load_idx;
6567430Sgblack@eecs.umich.edu        state->inst = load_inst;
6577430Sgblack@eecs.umich.edu        data_pkt->senderState = state;
6587430Sgblack@eecs.umich.edu
6597430Sgblack@eecs.umich.edu        if (!dcachePort->sendTiming(data_pkt)) {
6607430Sgblack@eecs.umich.edu            // Delete state and data packet because a load retry
6617430Sgblack@eecs.umich.edu            // initiates a pipeline restart; it does not retry.
6627430Sgblack@eecs.umich.edu            delete state;
6637430Sgblack@eecs.umich.edu            delete data_pkt->req;
6647430Sgblack@eecs.umich.edu            delete data_pkt;
6657430Sgblack@eecs.umich.edu
6667430Sgblack@eecs.umich.edu            req = NULL;
6677430Sgblack@eecs.umich.edu
6687430Sgblack@eecs.umich.edu            // If the access didn't succeed, tell the LSQ by setting
6697430Sgblack@eecs.umich.edu            // the retry thread id.
6707430Sgblack@eecs.umich.edu            lsq->setRetryTid(lsqID);
6717430Sgblack@eecs.umich.edu        }
6727430Sgblack@eecs.umich.edu    }
6737430Sgblack@eecs.umich.edu
6747430Sgblack@eecs.umich.edu    // If the cache was blocked, or has become blocked due to the access,
6757430Sgblack@eecs.umich.edu    // handle it.
6767430Sgblack@eecs.umich.edu    if (lsq->cacheBlocked()) {
6777430Sgblack@eecs.umich.edu        if (req)
6787430Sgblack@eecs.umich.edu            delete req;
6797430Sgblack@eecs.umich.edu
6807430Sgblack@eecs.umich.edu        ++lsqCacheBlocked;
6817430Sgblack@eecs.umich.edu
6827430Sgblack@eecs.umich.edu        iewStage->decrWb(load_inst->seqNum);
6837430Sgblack@eecs.umich.edu        // There's an older load that's already going to squash.
6847430Sgblack@eecs.umich.edu        if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
6857430Sgblack@eecs.umich.edu            return NoFault;
6867430Sgblack@eecs.umich.edu
6877430Sgblack@eecs.umich.edu        // Record that the load was blocked due to memory.  This
6887430Sgblack@eecs.umich.edu        // load will squash all instructions after it, be
6897430Sgblack@eecs.umich.edu        // refetched, and re-executed.
6907430Sgblack@eecs.umich.edu        isLoadBlocked = true;
6917430Sgblack@eecs.umich.edu        loadBlockedHandled = false;
6927430Sgblack@eecs.umich.edu        blockedLoadSeqNum = load_inst->seqNum;
6937430Sgblack@eecs.umich.edu        // No fault occurred, even though the interface is blocked.
6947430Sgblack@eecs.umich.edu        return NoFault;
6957430Sgblack@eecs.umich.edu    }
6967430Sgblack@eecs.umich.edu
6977430Sgblack@eecs.umich.edu    return NoFault;
6987430Sgblack@eecs.umich.edu}
6997430Sgblack@eecs.umich.edu
7007430Sgblack@eecs.umich.edutemplate <class Impl>
7017430Sgblack@eecs.umich.edutemplate <class T>
7027430Sgblack@eecs.umich.eduFault
7037430Sgblack@eecs.umich.eduLSQUnit<Impl>::write(Request *req, T &data, int store_idx)
7047430Sgblack@eecs.umich.edu{
7057430Sgblack@eecs.umich.edu    assert(storeQueue[store_idx].inst);
7067430Sgblack@eecs.umich.edu
7077430Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
7087430Sgblack@eecs.umich.edu            " | storeHead:%i [sn:%i]\n",
7097430Sgblack@eecs.umich.edu            store_idx, req->getPaddr(), data, storeHead,
7107430Sgblack@eecs.umich.edu            storeQueue[store_idx].inst->seqNum);
7117430Sgblack@eecs.umich.edu
7127430Sgblack@eecs.umich.edu    storeQueue[store_idx].req = req;
7137430Sgblack@eecs.umich.edu    storeQueue[store_idx].size = sizeof(T);
7147430Sgblack@eecs.umich.edu    assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
7157430Sgblack@eecs.umich.edu
7167430Sgblack@eecs.umich.edu    T gData = htog(data);
7177430Sgblack@eecs.umich.edu    memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
7187430Sgblack@eecs.umich.edu
7197430Sgblack@eecs.umich.edu    // This function only writes the data to the store queue, so no fault
7207430Sgblack@eecs.umich.edu    // can happen here.
7217430Sgblack@eecs.umich.edu    return NoFault;
7227430Sgblack@eecs.umich.edu}
7237430Sgblack@eecs.umich.edu
7247430Sgblack@eecs.umich.edu#endif // __CPU_O3_LSQ_UNIT_HH__
7257430Sgblack@eecs.umich.edu