lsq_unit.hh revision 4395
16313Sgblack@eecs.umich.edu/*
212529Sgiacomo.travaglini@arm.com * Copyright (c) 2004-2006 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 * Authors: Kevin Lim
296313Sgblack@eecs.umich.edu *          Korey Sewell
306313Sgblack@eecs.umich.edu */
316313Sgblack@eecs.umich.edu
326313Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__
336313Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__
346313Sgblack@eecs.umich.edu
356313Sgblack@eecs.umich.edu#include <algorithm>
366313Sgblack@eecs.umich.edu#include <cstring>
376313Sgblack@eecs.umich.edu#include <map>
386313Sgblack@eecs.umich.edu#include <queue>
396313Sgblack@eecs.umich.edu
406313Sgblack@eecs.umich.edu#include "arch/faults.hh"
416313Sgblack@eecs.umich.edu#include "arch/locked_mem.hh"
426313Sgblack@eecs.umich.edu#include "config/full_system.hh"
436313Sgblack@eecs.umich.edu#include "base/hashmap.hh"
447404SAli.Saidi@ARM.com#include "cpu/inst_seq.hh"
456313Sgblack@eecs.umich.edu#include "mem/packet.hh"
4610461SAndreas.Sandberg@ARM.com#include "mem/port.hh"
4712479SCurtis.Dunham@arm.com
486333Sgblack@eecs.umich.edu/**
4910037SARM gem5 Developers * Class that implements the actual LQ and SQ for each specific
507404SAli.Saidi@ARM.com * thread.  Both are circular queues; load entries are freed upon
516313Sgblack@eecs.umich.edu * committing, while store entries are freed once they writeback. The
5212109SRekai.GonzalezAlberquilla@arm.com * LSQUnit tracks if there are memory ordering violations, and also
538232Snate@binkert.org * detects partial load to store forwarding cases (a store only has
5412109SRekai.GonzalezAlberquilla@arm.com * part of a load's data) that requires the load to wait until the
559384SAndreas.Sandberg@arm.com * store writes back. In the former case it holds onto the instruction
5611165SRekai.GonzalezAlberquilla@arm.com * until the dependence unit looks at it, and in the latter it stalls
576313Sgblack@eecs.umich.edu * the LSQ until the store writes back. At that point the load is
589384SAndreas.Sandberg@arm.com * replayed.
5910461SAndreas.Sandberg@ARM.com */
606333Sgblack@eecs.umich.edutemplate <class Impl>
616313Sgblack@eecs.umich.educlass LSQUnit {
626313Sgblack@eecs.umich.edu  protected:
636313Sgblack@eecs.umich.edu    typedef TheISA::IntReg IntReg;
646313Sgblack@eecs.umich.edu  public:
656313Sgblack@eecs.umich.edu    typedef typename Impl::Params Params;
669384SAndreas.Sandberg@arm.com    typedef typename Impl::O3CPU O3CPU;
676313Sgblack@eecs.umich.edu    typedef typename Impl::DynInstPtr DynInstPtr;
686313Sgblack@eecs.umich.edu    typedef typename Impl::CPUPol::IEW IEW;
6910037SARM gem5 Developers    typedef typename Impl::CPUPol::LSQ LSQ;
7010037SARM gem5 Developers    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
7110037SARM gem5 Developers
7211165SRekai.GonzalezAlberquilla@arm.com  public:
7311165SRekai.GonzalezAlberquilla@arm.com    /** Constructs an LSQ unit. init() must be called prior to use. */
7412109SRekai.GonzalezAlberquilla@arm.com    LSQUnit();
7511165SRekai.GonzalezAlberquilla@arm.com
7610461SAndreas.Sandberg@ARM.com    /** Initializes the LSQ unit with the specified number of entries. */
7710461SAndreas.Sandberg@ARM.com    void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
7810461SAndreas.Sandberg@ARM.com              unsigned maxLQEntries, unsigned maxSQEntries, unsigned id);
7910461SAndreas.Sandberg@ARM.com
8010461SAndreas.Sandberg@ARM.com    /** Returns the name of the LSQ unit. */
8110461SAndreas.Sandberg@ARM.com    std::string name() const;
8210844Sandreas.sandberg@arm.com
8310844Sandreas.sandberg@arm.com    /** Registers statistics. */
8410844Sandreas.sandberg@arm.com    void regStats();
8513531Sjairo.balart@metempsy.com
8613531Sjairo.balart@metempsy.com    /** Sets the pointer to the dcache port. */
8713531Sjairo.balart@metempsy.com    void setDcachePort(Port *dcache_port);
8810037SARM gem5 Developers
8911771SCurtis.Dunham@arm.com    /** Switches out LSQ unit. */
9010037SARM gem5 Developers    void switchOut();
9110037SARM gem5 Developers
9210037SARM gem5 Developers    /** Takes over from another CPU's thread. */
9313173Sgiacomo.travaglini@arm.com    void takeOverFrom();
9410037SARM gem5 Developers
9513531Sjairo.balart@metempsy.com    /** Returns if the LSQ is switched out. */
9613114Sgiacomo.travaglini@arm.com    bool isSwitchedOut() { return switchedOut; }
9710037SARM gem5 Developers
9812714Sgiacomo.travaglini@arm.com    /** Ticks the LSQ unit, which in this case only resets the number of
9912714Sgiacomo.travaglini@arm.com     * used cache ports.
10012714Sgiacomo.travaglini@arm.com     * @todo: Move the number of used ports up to the LSQ level so it can
10112714Sgiacomo.travaglini@arm.com     * be shared by all LSQ units.
10212714Sgiacomo.travaglini@arm.com     */
10312714Sgiacomo.travaglini@arm.com    void tick() { usedPorts = 0; }
10412478SCurtis.Dunham@arm.com
10510037SARM gem5 Developers    /** Inserts an instruction. */
10612477SCurtis.Dunham@arm.com    void insert(DynInstPtr &inst);
10712477SCurtis.Dunham@arm.com    /** Inserts a load instruction. */
10812478SCurtis.Dunham@arm.com    void insertLoad(DynInstPtr &load_inst);
10912478SCurtis.Dunham@arm.com    /** Inserts a store instruction. */
11012478SCurtis.Dunham@arm.com    void insertStore(DynInstPtr &store_inst);
11112478SCurtis.Dunham@arm.com
11212478SCurtis.Dunham@arm.com    /** Executes a load instruction. */
11312478SCurtis.Dunham@arm.com    Fault executeLoad(DynInstPtr &inst);
11412478SCurtis.Dunham@arm.com
11512478SCurtis.Dunham@arm.com    Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
11612478SCurtis.Dunham@arm.com    /** Executes a store instruction. */
11712478SCurtis.Dunham@arm.com    Fault executeStore(DynInstPtr &inst);
11812478SCurtis.Dunham@arm.com
11912478SCurtis.Dunham@arm.com    /** Commits the head load. */
12012478SCurtis.Dunham@arm.com    void commitLoad();
12112478SCurtis.Dunham@arm.com    /** Commits loads older than a specific sequence number. */
12212478SCurtis.Dunham@arm.com    void commitLoads(InstSeqNum &youngest_inst);
12312478SCurtis.Dunham@arm.com
12410037SARM gem5 Developers    /** Commits stores older than a specific sequence number. */
12510037SARM gem5 Developers    void commitStores(InstSeqNum &youngest_inst);
12612477SCurtis.Dunham@arm.com
12712479SCurtis.Dunham@arm.com    /** Writes back stores. */
12812477SCurtis.Dunham@arm.com    void writebackStores();
12912477SCurtis.Dunham@arm.com
13012477SCurtis.Dunham@arm.com    /** Completes the data access that has been returned from the
13112479SCurtis.Dunham@arm.com     * memory system. */
13212477SCurtis.Dunham@arm.com    void completeDataAccess(PacketPtr pkt);
13312477SCurtis.Dunham@arm.com
13412477SCurtis.Dunham@arm.com    /** Clears all the entries in the LQ. */
13512477SCurtis.Dunham@arm.com    void clearLQ();
13612477SCurtis.Dunham@arm.com
13712477SCurtis.Dunham@arm.com    /** Clears all the entries in the SQ. */
13812477SCurtis.Dunham@arm.com    void clearSQ();
13912478SCurtis.Dunham@arm.com
14012478SCurtis.Dunham@arm.com    /** Resizes the LQ to a given size. */
14112478SCurtis.Dunham@arm.com    void resizeLQ(unsigned size);
14212478SCurtis.Dunham@arm.com
14312478SCurtis.Dunham@arm.com    /** Resizes the SQ to a given size. */
14412478SCurtis.Dunham@arm.com    void resizeSQ(unsigned size);
14512478SCurtis.Dunham@arm.com
14612478SCurtis.Dunham@arm.com    /** Squashes all instructions younger than a specific sequence number. */
14712478SCurtis.Dunham@arm.com    void squash(const InstSeqNum &squashed_num);
14812478SCurtis.Dunham@arm.com
14912478SCurtis.Dunham@arm.com    /** Returns if there is a memory ordering violation. Value is reset upon
15012478SCurtis.Dunham@arm.com     * call to getMemDepViolator().
15112478SCurtis.Dunham@arm.com     */
15212478SCurtis.Dunham@arm.com    bool violation() { return memDepViolator; }
15312478SCurtis.Dunham@arm.com
15412478SCurtis.Dunham@arm.com    /** Returns the memory ordering violator. */
15512479SCurtis.Dunham@arm.com    DynInstPtr getMemDepViolator();
15612479SCurtis.Dunham@arm.com
15712479SCurtis.Dunham@arm.com    /** Returns if a load became blocked due to the memory system. */
15812479SCurtis.Dunham@arm.com    bool loadBlocked()
15912479SCurtis.Dunham@arm.com    { return isLoadBlocked; }
16012479SCurtis.Dunham@arm.com
16112479SCurtis.Dunham@arm.com    /** Clears the signal that a load became blocked. */
16212479SCurtis.Dunham@arm.com    void clearLoadBlocked()
16312479SCurtis.Dunham@arm.com    { isLoadBlocked = false; }
16412479SCurtis.Dunham@arm.com
16512479SCurtis.Dunham@arm.com    /** Returns if the blocked load was handled. */
16612479SCurtis.Dunham@arm.com    bool isLoadBlockedHandled()
16712479SCurtis.Dunham@arm.com    { return loadBlockedHandled; }
16812479SCurtis.Dunham@arm.com
16912479SCurtis.Dunham@arm.com    /** Records the blocked load as being handled. */
17012479SCurtis.Dunham@arm.com    void setLoadBlockedHandled()
17112479SCurtis.Dunham@arm.com    { loadBlockedHandled = true; }
17212479SCurtis.Dunham@arm.com
17312479SCurtis.Dunham@arm.com    /** Returns the number of free entries (min of free LQ and SQ entries). */
17412479SCurtis.Dunham@arm.com    unsigned numFreeEntries();
17512479SCurtis.Dunham@arm.com
17612479SCurtis.Dunham@arm.com    /** Returns the number of loads ready to execute. */
17712479SCurtis.Dunham@arm.com    int numLoadsReady();
17812479SCurtis.Dunham@arm.com
17912479SCurtis.Dunham@arm.com    /** Returns the number of loads in the LQ. */
18012479SCurtis.Dunham@arm.com    int numLoads() { return loads; }
18112479SCurtis.Dunham@arm.com
18212479SCurtis.Dunham@arm.com    /** Returns the number of stores in the SQ. */
18312479SCurtis.Dunham@arm.com    int numStores() { return stores; }
18412479SCurtis.Dunham@arm.com
18512479SCurtis.Dunham@arm.com    /** Returns if either the LQ or SQ is full. */
18612479SCurtis.Dunham@arm.com    bool isFull() { return lqFull() || sqFull(); }
18712479SCurtis.Dunham@arm.com
18812479SCurtis.Dunham@arm.com    /** Returns if the LQ is full. */
18912479SCurtis.Dunham@arm.com    bool lqFull() { return loads >= (LQEntries - 1); }
19012479SCurtis.Dunham@arm.com
19112479SCurtis.Dunham@arm.com    /** Returns if the SQ is full. */
19212479SCurtis.Dunham@arm.com    bool sqFull() { return stores >= (SQEntries - 1); }
19312479SCurtis.Dunham@arm.com
19412479SCurtis.Dunham@arm.com    /** Returns the number of instructions in the LSQ. */
19512479SCurtis.Dunham@arm.com    unsigned getCount() { return loads + stores; }
19612479SCurtis.Dunham@arm.com
19712479SCurtis.Dunham@arm.com    /** Returns if there are any stores to writeback. */
19812479SCurtis.Dunham@arm.com    bool hasStoresToWB() { return storesToWB; }
19912479SCurtis.Dunham@arm.com
20012479SCurtis.Dunham@arm.com    /** Returns the number of stores to writeback. */
20112479SCurtis.Dunham@arm.com    int numStoresToWB() { return storesToWB; }
20212479SCurtis.Dunham@arm.com
20312479SCurtis.Dunham@arm.com    /** Returns if the LSQ unit will writeback on this cycle. */
20412479SCurtis.Dunham@arm.com    bool willWB() { return storeQueue[storeWBIdx].canWB &&
20512479SCurtis.Dunham@arm.com                        !storeQueue[storeWBIdx].completed &&
20612479SCurtis.Dunham@arm.com                        !isStoreBlocked; }
20712479SCurtis.Dunham@arm.com
20812479SCurtis.Dunham@arm.com    /** Handles doing the retry. */
20912479SCurtis.Dunham@arm.com    void recvRetry();
21012479SCurtis.Dunham@arm.com
21112479SCurtis.Dunham@arm.com  private:
21212479SCurtis.Dunham@arm.com    /** Writes back the instruction, sending it to IEW. */
21312668Sgiacomo.travaglini@arm.com    void writeback(DynInstPtr &inst, PacketPtr pkt);
21412668Sgiacomo.travaglini@arm.com
21512668Sgiacomo.travaglini@arm.com    /** Handles completing the send of a store to memory. */
21612668Sgiacomo.travaglini@arm.com    void storePostSend(PacketPtr pkt);
21712668Sgiacomo.travaglini@arm.com
21812479SCurtis.Dunham@arm.com    /** Completes the store at the specified index. */
21912479SCurtis.Dunham@arm.com    void completeStore(int store_idx);
22012479SCurtis.Dunham@arm.com
22112479SCurtis.Dunham@arm.com    /** Increments the given store index (circular queue). */
22212479SCurtis.Dunham@arm.com    inline void incrStIdx(int &store_idx);
22312479SCurtis.Dunham@arm.com    /** Decrements the given store index (circular queue). */
22412479SCurtis.Dunham@arm.com    inline void decrStIdx(int &store_idx);
22512479SCurtis.Dunham@arm.com    /** Increments the given load index (circular queue). */
22612479SCurtis.Dunham@arm.com    inline void incrLdIdx(int &load_idx);
22712479SCurtis.Dunham@arm.com    /** Decrements the given load index (circular queue). */
22812479SCurtis.Dunham@arm.com    inline void decrLdIdx(int &load_idx);
22912479SCurtis.Dunham@arm.com
23012479SCurtis.Dunham@arm.com  public:
23112668Sgiacomo.travaglini@arm.com    /** Debugging function to dump instructions in the LSQ. */
23212668Sgiacomo.travaglini@arm.com    void dumpInsts();
23312668Sgiacomo.travaglini@arm.com
23412668Sgiacomo.travaglini@arm.com  private:
23512668Sgiacomo.travaglini@arm.com    /** Pointer to the CPU. */
23613395Sgiacomo.travaglini@arm.com    O3CPU *cpu;
23713395Sgiacomo.travaglini@arm.com
23813395Sgiacomo.travaglini@arm.com    /** Pointer to the IEW stage. */
23913395Sgiacomo.travaglini@arm.com    IEW *iewStage;
24013395Sgiacomo.travaglini@arm.com
24112479SCurtis.Dunham@arm.com    /** Pointer to the LSQ. */
24212479SCurtis.Dunham@arm.com    LSQ *lsq;
24312479SCurtis.Dunham@arm.com
24412479SCurtis.Dunham@arm.com    /** Pointer to the dcache port.  Used only for sending. */
24512479SCurtis.Dunham@arm.com    Port *dcachePort;
24612479SCurtis.Dunham@arm.com
24712479SCurtis.Dunham@arm.com    /** Derived class to hold any sender state the LSQ needs. */
24812479SCurtis.Dunham@arm.com    class LSQSenderState : public Packet::SenderState
24912479SCurtis.Dunham@arm.com    {
25012479SCurtis.Dunham@arm.com      public:
25112479SCurtis.Dunham@arm.com        /** Default constructor. */
25212479SCurtis.Dunham@arm.com        LSQSenderState()
25312479SCurtis.Dunham@arm.com            : noWB(false)
25412479SCurtis.Dunham@arm.com        { }
25512479SCurtis.Dunham@arm.com
25612479SCurtis.Dunham@arm.com        /** Instruction who initiated the access to memory. */
25712479SCurtis.Dunham@arm.com        DynInstPtr inst;
25812479SCurtis.Dunham@arm.com        /** Whether or not it is a load. */
25912479SCurtis.Dunham@arm.com        bool isLoad;
26012479SCurtis.Dunham@arm.com        /** The LQ/SQ index of the instruction. */
26112479SCurtis.Dunham@arm.com        int idx;
26212479SCurtis.Dunham@arm.com        /** Whether or not the instruction will need to writeback. */
26312479SCurtis.Dunham@arm.com        bool noWB;
26412479SCurtis.Dunham@arm.com    };
26512479SCurtis.Dunham@arm.com
26612479SCurtis.Dunham@arm.com    /** Writeback event, specifically for when stores forward data to loads. */
26712479SCurtis.Dunham@arm.com    class WritebackEvent : public Event {
26812479SCurtis.Dunham@arm.com      public:
26912479SCurtis.Dunham@arm.com        /** Constructs a writeback event. */
27012479SCurtis.Dunham@arm.com        WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr);
27112479SCurtis.Dunham@arm.com
27212479SCurtis.Dunham@arm.com        /** Processes the writeback event. */
27312479SCurtis.Dunham@arm.com        void process();
27412479SCurtis.Dunham@arm.com
27512479SCurtis.Dunham@arm.com        /** Returns the description of this event. */
27612479SCurtis.Dunham@arm.com        const char *description();
27712479SCurtis.Dunham@arm.com
27812479SCurtis.Dunham@arm.com      private:
27912479SCurtis.Dunham@arm.com        /** Instruction whose results are being written back. */
28012479SCurtis.Dunham@arm.com        DynInstPtr inst;
28112479SCurtis.Dunham@arm.com
28212479SCurtis.Dunham@arm.com        /** The packet that would have been sent to memory. */
28312479SCurtis.Dunham@arm.com        PacketPtr pkt;
28412479SCurtis.Dunham@arm.com
28512479SCurtis.Dunham@arm.com        /** The pointer to the LSQ unit that issued the store. */
28612479SCurtis.Dunham@arm.com        LSQUnit<Impl> *lsqPtr;
28712479SCurtis.Dunham@arm.com    };
28812479SCurtis.Dunham@arm.com
28912479SCurtis.Dunham@arm.com  public:
29012479SCurtis.Dunham@arm.com    struct SQEntry {
29112479SCurtis.Dunham@arm.com        /** Constructs an empty store queue entry. */
29212479SCurtis.Dunham@arm.com        SQEntry()
29312479SCurtis.Dunham@arm.com            : inst(NULL), req(NULL), size(0),
29412479SCurtis.Dunham@arm.com              canWB(0), committed(0), completed(0)
29512479SCurtis.Dunham@arm.com        {
29612479SCurtis.Dunham@arm.com            std::memset(data, 0, sizeof(data));
29712479SCurtis.Dunham@arm.com        }
29812479SCurtis.Dunham@arm.com
29912479SCurtis.Dunham@arm.com        /** Constructs a store queue entry for a given instruction. */
30012479SCurtis.Dunham@arm.com        SQEntry(DynInstPtr &_inst)
30112479SCurtis.Dunham@arm.com            : inst(_inst), req(NULL), size(0),
30212479SCurtis.Dunham@arm.com              canWB(0), committed(0), completed(0)
30312479SCurtis.Dunham@arm.com        {
30412479SCurtis.Dunham@arm.com            std::memset(data, 0, sizeof(data));
30512479SCurtis.Dunham@arm.com        }
30612479SCurtis.Dunham@arm.com
30712479SCurtis.Dunham@arm.com        /** The store instruction. */
30812479SCurtis.Dunham@arm.com        DynInstPtr inst;
30912479SCurtis.Dunham@arm.com        /** The request for the store. */
31012479SCurtis.Dunham@arm.com        RequestPtr req;
31112479SCurtis.Dunham@arm.com        /** The size of the store. */
31212479SCurtis.Dunham@arm.com        int size;
31312479SCurtis.Dunham@arm.com        /** The store data. */
31412479SCurtis.Dunham@arm.com        char data[sizeof(IntReg)];
31512479SCurtis.Dunham@arm.com        /** Whether or not the store can writeback. */
31612479SCurtis.Dunham@arm.com        bool canWB;
31712479SCurtis.Dunham@arm.com        /** Whether or not the store is committed. */
31812479SCurtis.Dunham@arm.com        bool committed;
31912479SCurtis.Dunham@arm.com        /** Whether or not the store is completed. */
32012479SCurtis.Dunham@arm.com        bool completed;
32112479SCurtis.Dunham@arm.com    };
32212479SCurtis.Dunham@arm.com
32312479SCurtis.Dunham@arm.com  private:
32412479SCurtis.Dunham@arm.com    /** The LSQUnit thread id. */
32512479SCurtis.Dunham@arm.com    unsigned lsqID;
32612479SCurtis.Dunham@arm.com
32712479SCurtis.Dunham@arm.com    /** The store queue. */
32812479SCurtis.Dunham@arm.com    std::vector<SQEntry> storeQueue;
32912479SCurtis.Dunham@arm.com
33012479SCurtis.Dunham@arm.com    /** The load queue. */
33112479SCurtis.Dunham@arm.com    std::vector<DynInstPtr> loadQueue;
33212479SCurtis.Dunham@arm.com
33312479SCurtis.Dunham@arm.com    /** The number of LQ entries, plus a sentinel entry (circular queue).
33412479SCurtis.Dunham@arm.com     *  @todo: Consider having var that records the true number of LQ entries.
33512479SCurtis.Dunham@arm.com     */
33612479SCurtis.Dunham@arm.com    unsigned LQEntries;
33712479SCurtis.Dunham@arm.com    /** The number of SQ entries, plus a sentinel entry (circular queue).
33812479SCurtis.Dunham@arm.com     *  @todo: Consider having var that records the true number of SQ entries.
33912479SCurtis.Dunham@arm.com     */
34012479SCurtis.Dunham@arm.com    unsigned SQEntries;
34112479SCurtis.Dunham@arm.com
34212479SCurtis.Dunham@arm.com    /** The number of load instructions in the LQ. */
34312479SCurtis.Dunham@arm.com    int loads;
34412479SCurtis.Dunham@arm.com    /** The number of store instructions in the SQ. */
34512479SCurtis.Dunham@arm.com    int stores;
34612479SCurtis.Dunham@arm.com    /** The number of store instructions in the SQ waiting to writeback. */
34712479SCurtis.Dunham@arm.com    int storesToWB;
34812479SCurtis.Dunham@arm.com
34912479SCurtis.Dunham@arm.com    /** The index of the head instruction in the LQ. */
35012479SCurtis.Dunham@arm.com    int loadHead;
35112479SCurtis.Dunham@arm.com    /** The index of the tail instruction in the LQ. */
35212479SCurtis.Dunham@arm.com    int loadTail;
35312479SCurtis.Dunham@arm.com
35412479SCurtis.Dunham@arm.com    /** The index of the head instruction in the SQ. */
35512479SCurtis.Dunham@arm.com    int storeHead;
35610037SARM gem5 Developers    /** The index of the first instruction that may be ready to be
35710037SARM gem5 Developers     * written back, and has not yet been written back.
35812477SCurtis.Dunham@arm.com     */
35912479SCurtis.Dunham@arm.com    int storeWBIdx;
36012479SCurtis.Dunham@arm.com    /** The index of the tail instruction in the SQ. */
36112477SCurtis.Dunham@arm.com    int storeTail;
36210037SARM gem5 Developers
36312477SCurtis.Dunham@arm.com    /// @todo Consider moving to a more advanced model with write vs read ports
36410037SARM gem5 Developers    /** The number of cache ports available each cycle. */
3656333Sgblack@eecs.umich.edu    int cachePorts;
3666718Sgblack@eecs.umich.edu
3676718Sgblack@eecs.umich.edu    /** The number of used cache ports in this cycle. */
3686718Sgblack@eecs.umich.edu    int usedPorts;
3696718Sgblack@eecs.umich.edu
3706718Sgblack@eecs.umich.edu    /** Is the LSQ switched out. */
37110037SARM gem5 Developers    bool switchedOut;
37210037SARM gem5 Developers
37310037SARM gem5 Developers    //list<InstSeqNum> mshrSeqNums;
37410037SARM gem5 Developers
37510037SARM gem5 Developers    /** Wire to read information from the issue stage time queue. */
37610037SARM gem5 Developers    typename TimeBuffer<IssueStruct>::wire fromIssue;
37710037SARM gem5 Developers
37810037SARM gem5 Developers    /** Whether or not the LSQ is stalled. */
37910037SARM gem5 Developers    bool stalled;
38010037SARM gem5 Developers    /** The store that causes the stall due to partial store to load
38110037SARM gem5 Developers     * forwarding.
38210037SARM gem5 Developers     */
38310037SARM gem5 Developers    InstSeqNum stallingStoreIsn;
38410037SARM gem5 Developers    /** The index of the above store. */
38510037SARM gem5 Developers    int stallingLoadIdx;
38610037SARM gem5 Developers
38710037SARM gem5 Developers    /** The packet that needs to be retried. */
38810037SARM gem5 Developers    PacketPtr retryPkt;
38910037SARM gem5 Developers
39010037SARM gem5 Developers    /** Whehter or not a store is blocked due to the memory system. */
39110037SARM gem5 Developers    bool isStoreBlocked;
39210037SARM gem5 Developers
39310037SARM gem5 Developers    /** Whether or not a load is blocked due to the memory system. */
39410037SARM gem5 Developers    bool isLoadBlocked;
39510037SARM gem5 Developers
39610037SARM gem5 Developers    /** Has the blocked load been handled. */
39710037SARM gem5 Developers    bool loadBlockedHandled;
39810037SARM gem5 Developers
39910037SARM gem5 Developers    /** The sequence number of the blocked load. */
40010037SARM gem5 Developers    InstSeqNum blockedLoadSeqNum;
40110037SARM gem5 Developers
40210037SARM gem5 Developers    /** The oldest load that caused a memory ordering violation. */
4036718Sgblack@eecs.umich.edu    DynInstPtr memDepViolator;
4046718Sgblack@eecs.umich.edu
4056313Sgblack@eecs.umich.edu    // Will also need how many read/write ports the Dcache has.  Or keep track
40610844Sandreas.sandberg@arm.com    // of that in stage that is one level up, and only call executeLoad/Store
40713531Sjairo.balart@metempsy.com    // the appropriate number of times.
40810037SARM gem5 Developers    /** Total number of loads forwaded from LSQ stores. */
40910037SARM gem5 Developers    Stats::Scalar<> lsqForwLoads;
41010037SARM gem5 Developers
41110037SARM gem5 Developers    /** Total number of loads ignored due to invalid addresses. */
41210037SARM gem5 Developers    Stats::Scalar<> invAddrLoads;
41310037SARM gem5 Developers
41410037SARM gem5 Developers    /** Total number of squashed loads. */
41510037SARM gem5 Developers    Stats::Scalar<> lsqSquashedLoads;
41610037SARM gem5 Developers
41710037SARM gem5 Developers    /** Total number of responses from the memory system that are
41810037SARM gem5 Developers     * ignored due to the instruction already being squashed. */
41910037SARM gem5 Developers    Stats::Scalar<> lsqIgnoredResponses;
42010037SARM gem5 Developers
4216313Sgblack@eecs.umich.edu    /** Tota number of memory ordering violations. */
4227427Sgblack@eecs.umich.edu    Stats::Scalar<> lsqMemOrderViolation;
42313114Sgiacomo.travaglini@arm.com
42413114Sgiacomo.travaglini@arm.com    /** Total number of squashed stores. */
42513393Sgiacomo.travaglini@arm.com    Stats::Scalar<> lsqSquashedStores;
42610037SARM gem5 Developers
42713114Sgiacomo.travaglini@arm.com    /** Total number of software prefetches ignored due to invalid addresses. */
42813114Sgiacomo.travaglini@arm.com    Stats::Scalar<> invAddrSwpfs;
4296313Sgblack@eecs.umich.edu
43013114Sgiacomo.travaglini@arm.com    /** Ready loads blocked due to partial store-forwarding. */
43110035Sandreas.hansson@arm.com    Stats::Scalar<> lsqBlockedLoads;
4327405SAli.Saidi@ARM.com
4337405SAli.Saidi@ARM.com    /** Number of loads that were rescheduled. */
4347405SAli.Saidi@ARM.com    Stats::Scalar<> lsqRescheduledLoads;
4356313Sgblack@eecs.umich.edu
43612106SRekai.GonzalezAlberquilla@arm.com    /** Number of times the LSQ is blocked due to the cache. */
43712106SRekai.GonzalezAlberquilla@arm.com    Stats::Scalar<> lsqCacheBlocked;
43812106SRekai.GonzalezAlberquilla@arm.com
43912106SRekai.GonzalezAlberquilla@arm.com  public:
44012106SRekai.GonzalezAlberquilla@arm.com    /** Executes the load at the given index. */
44112106SRekai.GonzalezAlberquilla@arm.com    template <class T>
44212106SRekai.GonzalezAlberquilla@arm.com    Fault read(Request *req, T &data, int load_idx);
44312106SRekai.GonzalezAlberquilla@arm.com
44412109SRekai.GonzalezAlberquilla@arm.com    /** Executes the store at the given index. */
44512109SRekai.GonzalezAlberquilla@arm.com    template <class T>
44612109SRekai.GonzalezAlberquilla@arm.com    Fault write(Request *req, T &data, int store_idx);
44713545Sgiacomo.travaglini@arm.com
44813545Sgiacomo.travaglini@arm.com    /** Returns the index of the head load instruction. */
44912106SRekai.GonzalezAlberquilla@arm.com    int getLoadHead() { return loadHead; }
45012106SRekai.GonzalezAlberquilla@arm.com    /** Returns the sequence number of the head load instruction. */
45112106SRekai.GonzalezAlberquilla@arm.com    InstSeqNum getLoadHeadSeqNum()
45212106SRekai.GonzalezAlberquilla@arm.com    {
45312106SRekai.GonzalezAlberquilla@arm.com        if (loadQueue[loadHead]) {
45412106SRekai.GonzalezAlberquilla@arm.com            return loadQueue[loadHead]->seqNum;
45512106SRekai.GonzalezAlberquilla@arm.com        } else {
45612106SRekai.GonzalezAlberquilla@arm.com            return 0;
4576313Sgblack@eecs.umich.edu        }
45810035Sandreas.hansson@arm.com
4596313Sgblack@eecs.umich.edu    }
4606718Sgblack@eecs.umich.edu
4616718Sgblack@eecs.umich.edu    /** Returns the index of the head store instruction. */
4626718Sgblack@eecs.umich.edu    int getStoreHead() { return storeHead; }
4636726Sgblack@eecs.umich.edu    /** Returns the sequence number of the head store instruction. */
4646726Sgblack@eecs.umich.edu    InstSeqNum getStoreHeadSeqNum()
46510037SARM gem5 Developers    {
46610037SARM gem5 Developers        if (storeQueue[storeHead].inst) {
46710037SARM gem5 Developers            return storeQueue[storeHead].inst->seqNum;
46810037SARM gem5 Developers        } else {
46910037SARM gem5 Developers            return 0;
47010037SARM gem5 Developers        }
47110037SARM gem5 Developers
47210037SARM gem5 Developers    }
47310037SARM gem5 Developers
47411574SCurtis.Dunham@arm.com    /** Returns whether or not the LSQ unit is stalled. */
47511574SCurtis.Dunham@arm.com    bool isStalled()  { return stalled; }
47610037SARM gem5 Developers};
47710037SARM gem5 Developers
47810037SARM gem5 Developerstemplate <class Impl>
47910037SARM gem5 Developerstemplate <class T>
48010037SARM gem5 DevelopersFault
48110037SARM gem5 DevelopersLSQUnit<Impl>::read(Request *req, T &data, int load_idx)
48213020Sshunhsingou@google.com{
48310037SARM gem5 Developers    DynInstPtr load_inst = loadQueue[load_idx];
4846718Sgblack@eecs.umich.edu
48510037SARM gem5 Developers    assert(load_inst);
4866718Sgblack@eecs.umich.edu
4876313Sgblack@eecs.umich.edu    assert(!load_inst->isExecuted());
4886313Sgblack@eecs.umich.edu
4896313Sgblack@eecs.umich.edu    // Make sure this isn't an uncacheable access
49010035Sandreas.hansson@arm.com    // A bit of a hackish way to get uncached accesses to work only if they're
4916313Sgblack@eecs.umich.edu    // at the head of the LSQ and are ready to commit (at the head of the ROB
49210338SCurtis.Dunham@arm.com    // too).
4936313Sgblack@eecs.umich.edu    if (req->isUncacheable() &&
4946313Sgblack@eecs.umich.edu        (load_idx != loadHead || !load_inst->isAtCommit())) {
4956313Sgblack@eecs.umich.edu        iewStage->rescheduleMemInst(load_inst);
4969920Syasuko.eckert@amd.com        ++lsqRescheduledLoads;
49712109SRekai.GonzalezAlberquilla@arm.com
49812109SRekai.GonzalezAlberquilla@arm.com        // Must delete request now that it wasn't handed off to
49912109SRekai.GonzalezAlberquilla@arm.com        // memory.  This is quite ugly.  @todo: Figure out the proper
50012109SRekai.GonzalezAlberquilla@arm.com        // place to really handle request deletes.
50112109SRekai.GonzalezAlberquilla@arm.com        delete req;
50212109SRekai.GonzalezAlberquilla@arm.com        return TheISA::genMachineCheckFault();
50312109SRekai.GonzalezAlberquilla@arm.com    }
50412109SRekai.GonzalezAlberquilla@arm.com
50512109SRekai.GonzalezAlberquilla@arm.com    // Check the SQ for any previous stores that might lead to forwarding
50612109SRekai.GonzalezAlberquilla@arm.com    int store_idx = load_inst->sqIdx;
50712109SRekai.GonzalezAlberquilla@arm.com
50812109SRekai.GonzalezAlberquilla@arm.com    int store_size = 0;
50912109SRekai.GonzalezAlberquilla@arm.com
51012109SRekai.GonzalezAlberquilla@arm.com    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
51110035Sandreas.hansson@arm.com            "storeHead: %i addr: %#x\n",
5129920Syasuko.eckert@amd.com            load_idx, store_idx, storeHead, req->getPaddr());
51310338SCurtis.Dunham@arm.com
5149920Syasuko.eckert@amd.com    if (req->isLocked()) {
5159920Syasuko.eckert@amd.com        // Disable recording the result temporarily.  Writing to misc
5169920Syasuko.eckert@amd.com        // regs normally updates the result, but this is not the
5177614Sminkyu.jeong@arm.com        // desired behavior when handling store conditionals.
51810035Sandreas.hansson@arm.com        load_inst->recordResult = false;
5197614Sminkyu.jeong@arm.com        TheISA::handleLockedRead(load_inst.get(), req);
52010338SCurtis.Dunham@arm.com        load_inst->recordResult = true;
52110037SARM gem5 Developers    }
52210037SARM gem5 Developers
5237614Sminkyu.jeong@arm.com    while (store_idx != -1) {
5247614Sminkyu.jeong@arm.com        // End once we've reached the top of the LSQ
5257614Sminkyu.jeong@arm.com        if (store_idx == storeWBIdx) {
52610037SARM gem5 Developers            break;
52710037SARM gem5 Developers        }
52810037SARM gem5 Developers
52910037SARM gem5 Developers        // Move the index to one younger
53010037SARM gem5 Developers        if (--store_idx < 0)
53110037SARM gem5 Developers            store_idx += SQEntries;
53210037SARM gem5 Developers
53310037SARM gem5 Developers        assert(storeQueue[store_idx].inst);
53410037SARM gem5 Developers
53510037SARM gem5 Developers        store_size = storeQueue[store_idx].size;
53610037SARM gem5 Developers
53710037SARM gem5 Developers        if (store_size == 0)
53810037SARM gem5 Developers            continue;
53910037SARM gem5 Developers        else if (storeQueue[store_idx].inst->uncacheable())
54010037SARM gem5 Developers            continue;
54110037SARM gem5 Developers
5427614Sminkyu.jeong@arm.com        assert(storeQueue[store_idx].inst->effAddrValid);
5437614Sminkyu.jeong@arm.com
54410037SARM gem5 Developers        // Check if the store data is within the lower and upper bounds of
5457614Sminkyu.jeong@arm.com        // addresses that the request needs.
5467614Sminkyu.jeong@arm.com        bool store_has_lower_limit =
54710037SARM gem5 Developers            req->getVaddr() >= storeQueue[store_idx].inst->effAddr;
5487614Sminkyu.jeong@arm.com        bool store_has_upper_limit =
5497614Sminkyu.jeong@arm.com            (req->getVaddr() + req->getSize()) <=
55010037SARM gem5 Developers            (storeQueue[store_idx].inst->effAddr + store_size);
5517614Sminkyu.jeong@arm.com        bool lower_load_has_store_part =
5527614Sminkyu.jeong@arm.com            req->getVaddr() < (storeQueue[store_idx].inst->effAddr +
55310037SARM gem5 Developers                           store_size);
5547614Sminkyu.jeong@arm.com        bool upper_load_has_store_part =
5557614Sminkyu.jeong@arm.com            (req->getVaddr() + req->getSize()) >
55610037SARM gem5 Developers            storeQueue[store_idx].inst->effAddr;
5577614Sminkyu.jeong@arm.com
5587614Sminkyu.jeong@arm.com        // If the store's data has all of the data needed, we can forward.
55910037SARM gem5 Developers        if ((store_has_lower_limit && store_has_upper_limit)) {
56010037SARM gem5 Developers            // Get shift amount for offset into the store's data.
56110037SARM gem5 Developers            int shift_amt = req->getVaddr() & (store_size - 1);
56210037SARM gem5 Developers
5637614Sminkyu.jeong@arm.com            memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
5647614Sminkyu.jeong@arm.com
56510037SARM gem5 Developers            assert(!load_inst->memData);
5667614Sminkyu.jeong@arm.com            load_inst->memData = new uint8_t[64];
5677614Sminkyu.jeong@arm.com
5687614Sminkyu.jeong@arm.com            memcpy(load_inst->memData,
5697614Sminkyu.jeong@arm.com                    storeQueue[store_idx].data + shift_amt, req->getSize());
57010037SARM gem5 Developers
5717614Sminkyu.jeong@arm.com            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
5727614Sminkyu.jeong@arm.com                    "addr %#x, data %#x\n",
57310037SARM gem5 Developers                    store_idx, req->getVaddr(), data);
57410037SARM gem5 Developers
57510037SARM gem5 Developers            PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq,
57610037SARM gem5 Developers                                            Packet::Broadcast);
57710037SARM gem5 Developers            data_pkt->dataStatic(load_inst->memData);
57810037SARM gem5 Developers
57910037SARM gem5 Developers            WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this);
58010037SARM gem5 Developers
58110037SARM gem5 Developers            // We'll say this has a 1 cycle load-store forwarding latency
58210037SARM gem5 Developers            // for now.
58310037SARM gem5 Developers            // @todo: Need to make this a parameter.
58410037SARM gem5 Developers            wb->schedule(curTick);
58510037SARM gem5 Developers
58610037SARM gem5 Developers            ++lsqForwLoads;
58710037SARM gem5 Developers            return NoFault;
58810037SARM gem5 Developers        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
58910037SARM gem5 Developers                   (store_has_upper_limit && upper_load_has_store_part) ||
59010037SARM gem5 Developers                   (lower_load_has_store_part && upper_load_has_store_part)) {
59110037SARM gem5 Developers            // This is the partial store-load forwarding case where a store
59210037SARM gem5 Developers            // has only part of the load's data.
59310037SARM gem5 Developers
59410037SARM gem5 Developers            // If it's already been written back, then don't worry about
59510037SARM gem5 Developers            // stalling on it.
59610037SARM gem5 Developers            if (storeQueue[store_idx].completed) {
59710037SARM gem5 Developers                panic("Should not check one of these");
59810037SARM gem5 Developers                continue;
59910037SARM gem5 Developers            }
60010037SARM gem5 Developers
60110037SARM gem5 Developers            // Must stall load and force it to retry, so long as it's the oldest
60210037SARM gem5 Developers            // load that needs to do so.
60310037SARM gem5 Developers            if (!stalled ||
60410037SARM gem5 Developers                (stalled &&
60510037SARM gem5 Developers                 load_inst->seqNum <
60610037SARM gem5 Developers                 loadQueue[stallingLoadIdx]->seqNum)) {
60710037SARM gem5 Developers                stalled = true;
60810037SARM gem5 Developers                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
60910037SARM gem5 Developers                stallingLoadIdx = load_idx;
61010037SARM gem5 Developers            }
61110037SARM gem5 Developers
61210037SARM gem5 Developers            // Tell IQ/mem dep unit that this instruction will need to be
61310037SARM gem5 Developers            // rescheduled eventually
61410037SARM gem5 Developers            iewStage->rescheduleMemInst(load_inst);
61510037SARM gem5 Developers            iewStage->decrWb(load_inst->seqNum);
61610037SARM gem5 Developers            load_inst->clearIssued();
61710037SARM gem5 Developers            ++lsqRescheduledLoads;
61810037SARM gem5 Developers
61910037SARM gem5 Developers            // Do not generate a writeback event as this instruction is not
62010037SARM gem5 Developers            // complete.
62110037SARM gem5 Developers            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
62210037SARM gem5 Developers                    "Store idx %i to load addr %#x\n",
62311771SCurtis.Dunham@arm.com                    store_idx, req->getVaddr());
62410037SARM gem5 Developers
62510037SARM gem5 Developers            // Must delete request now that it wasn't handed off to
62610037SARM gem5 Developers            // memory.  This is quite ugly.  @todo: Figure out the
62710037SARM gem5 Developers            // proper place to really handle request deletes.
6287614Sminkyu.jeong@arm.com            delete req;
62910037SARM gem5 Developers
6307614Sminkyu.jeong@arm.com            return NoFault;
6317614Sminkyu.jeong@arm.com        }
63211771SCurtis.Dunham@arm.com    }
63311771SCurtis.Dunham@arm.com
63411771SCurtis.Dunham@arm.com    // If there's no forwarding case, then go access memory
63511771SCurtis.Dunham@arm.com    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
63611771SCurtis.Dunham@arm.com            load_inst->seqNum, load_inst->readPC());
63711771SCurtis.Dunham@arm.com
63811771SCurtis.Dunham@arm.com    assert(!load_inst->memData);
63911771SCurtis.Dunham@arm.com    load_inst->memData = new uint8_t[64];
64011771SCurtis.Dunham@arm.com
64111771SCurtis.Dunham@arm.com    ++usedPorts;
64211771SCurtis.Dunham@arm.com
64311771SCurtis.Dunham@arm.com    // if we the cache is not blocked, do cache access
64411771SCurtis.Dunham@arm.com    if (!lsq->cacheBlocked()) {
64511771SCurtis.Dunham@arm.com        PacketPtr data_pkt =
64611771SCurtis.Dunham@arm.com            new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
64711771SCurtis.Dunham@arm.com        data_pkt->dataStatic(load_inst->memData);
64811771SCurtis.Dunham@arm.com
64911771SCurtis.Dunham@arm.com        LSQSenderState *state = new LSQSenderState;
65011771SCurtis.Dunham@arm.com        state->isLoad = true;
65111771SCurtis.Dunham@arm.com        state->idx = load_idx;
65211771SCurtis.Dunham@arm.com        state->inst = load_inst;
65310905Sandreas.sandberg@arm.com        data_pkt->senderState = state;
6547733SAli.Saidi@ARM.com
6557733SAli.Saidi@ARM.com        if (!dcachePort->sendTiming(data_pkt)) {
65612529Sgiacomo.travaglini@arm.com            Packet::Result result = data_pkt->result;
65710037SARM gem5 Developers
65811771SCurtis.Dunham@arm.com            // Delete state and data packet because a load retry
65910037SARM gem5 Developers            // initiates a pipeline restart; it does not retry.
66010037SARM gem5 Developers            delete state;
66110037SARM gem5 Developers            delete data_pkt->req;
66210037SARM gem5 Developers            delete data_pkt;
66313114Sgiacomo.travaglini@arm.com
6647733SAli.Saidi@ARM.com            req = NULL;
66510905Sandreas.sandberg@arm.com
6667733SAli.Saidi@ARM.com            if (result == Packet::BadAddress) {
6677733SAli.Saidi@ARM.com                return TheISA::genMachineCheckFault();
66812529Sgiacomo.travaglini@arm.com            }
6697733SAli.Saidi@ARM.com
6707733SAli.Saidi@ARM.com            // If the access didn't succeed, tell the LSQ by setting
67110037SARM gem5 Developers            // the retry thread id.
67211771SCurtis.Dunham@arm.com            lsq->setRetryTid(lsqID);
67310037SARM gem5 Developers        }
67410037SARM gem5 Developers    }
67510037SARM gem5 Developers
67610037SARM gem5 Developers    // If the cache was blocked, or has become blocked due to the access,
67713114Sgiacomo.travaglini@arm.com    // handle it.
6787733SAli.Saidi@ARM.com    if (lsq->cacheBlocked()) {
6796313Sgblack@eecs.umich.edu        if (req)
68012972Sandreas.sandberg@arm.com            delete req;
6819461Snilay@cs.wisc.edu
68211165SRekai.GonzalezAlberquilla@arm.com        ++lsqCacheBlocked;
68311165SRekai.GonzalezAlberquilla@arm.com
68412109SRekai.GonzalezAlberquilla@arm.com        iewStage->decrWb(load_inst->seqNum);
68512109SRekai.GonzalezAlberquilla@arm.com        // There's an older load that's already going to squash.
68612109SRekai.GonzalezAlberquilla@arm.com        if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
68712109SRekai.GonzalezAlberquilla@arm.com            return NoFault;
68812109SRekai.GonzalezAlberquilla@arm.com
68912109SRekai.GonzalezAlberquilla@arm.com        // Record that the load was blocked due to memory.  This
6909553Sandreas.hansson@arm.com        // load will squash all instructions after it, be
6919553Sandreas.hansson@arm.com        // refetched, and re-executed.
6929553Sandreas.hansson@arm.com        isLoadBlocked = true;
6939384SAndreas.Sandberg@arm.com        loadBlockedHandled = false;
6947400SAli.Saidi@ARM.com        blockedLoadSeqNum = load_inst->seqNum;
6959384SAndreas.Sandberg@arm.com        // No fault occurred, even though the interface is blocked.
6969384SAndreas.Sandberg@arm.com        return NoFault;
6979384SAndreas.Sandberg@arm.com    }
6986313Sgblack@eecs.umich.edu
6996313Sgblack@eecs.umich.edu    return NoFault;
7006313Sgblack@eecs.umich.edu}
70112109SRekai.GonzalezAlberquilla@arm.com
70212109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl>
70312109SRekai.GonzalezAlberquilla@arm.comtemplate <class T>
70412109SRekai.GonzalezAlberquilla@arm.comFault
70512109SRekai.GonzalezAlberquilla@arm.comLSQUnit<Impl>::write(Request *req, T &data, int store_idx)
70612109SRekai.GonzalezAlberquilla@arm.com{
70712109SRekai.GonzalezAlberquilla@arm.com    assert(storeQueue[store_idx].inst);
70812109SRekai.GonzalezAlberquilla@arm.com
70912109SRekai.GonzalezAlberquilla@arm.com    DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
71012109SRekai.GonzalezAlberquilla@arm.com            " | storeHead:%i [sn:%i]\n",
71112109SRekai.GonzalezAlberquilla@arm.com            store_idx, req->getPaddr(), data, storeHead,
71212109SRekai.GonzalezAlberquilla@arm.com            storeQueue[store_idx].inst->seqNum);
71312109SRekai.GonzalezAlberquilla@arm.com
7146313Sgblack@eecs.umich.edu    storeQueue[store_idx].req = req;
715    storeQueue[store_idx].size = sizeof(T);
716    assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
717
718    T gData = htog(data);
719    memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
720
721    // This function only writes the data to the store queue, so no fault
722    // can happen here.
723    return NoFault;
724}
725
726#endif // __CPU_O3_LSQ_UNIT_HH__
727