lsq_unit.hh revision 2307
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef __CPU_O3_LSQ_UNIT_HH__
30#define __CPU_O3_LSQ_UNIT_HH__
31
32#include <map>
33#include <queue>
34#include <algorithm>
35
36#include "config/full_system.hh"
37#include "base/hashmap.hh"
38#include "cpu/inst_seq.hh"
39#include "mem/mem_interface.hh"
40//#include "mem/page_table.hh"
41#include "sim/debug.hh"
42#include "sim/sim_object.hh"
43#include "arch/faults.hh"
44
45/**
46 * Class that implements the actual LQ and SQ for each specific thread.
47 * Both are circular queues; load entries are freed upon committing, while
48 * store entries are freed once they writeback. The LSQUnit tracks if there
49 * are memory ordering violations, and also detects partial load to store
50 * forwarding cases (a store only has part of a load's data) that requires
51 * the load to wait until the store writes back. In the former case it
52 * holds onto the instruction until the dependence unit looks at it, and
53 * in the latter it stalls the LSQ until the store writes back. At that
54 * point the load is replayed.
55 */
56template <class Impl>
57class LSQUnit {
58  protected:
59    typedef TheISA::IntReg IntReg;
60  public:
61    typedef typename Impl::Params Params;
62    typedef typename Impl::FullCPU FullCPU;
63    typedef typename Impl::DynInstPtr DynInstPtr;
64    typedef typename Impl::CPUPol::IEW IEW;
65    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
66
67  private:
68    class StoreCompletionEvent : public Event {
69      public:
70        /** Constructs a store completion event. */
71        StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr);
72
73        /** Processes the store completion event. */
74        void process();
75
76        /** Returns the description of this event. */
77        const char *description();
78
79      private:
80        /** The store index of the store being written back. */
81        int storeIdx;
82        /** The writeback event for the store.  Needed for store
83         * conditionals.
84         */
85        Event *wbEvent;
86        /** The pointer to the LSQ unit that issued the store. */
87        LSQUnit<Impl> *lsqPtr;
88    };
89
90    friend class StoreCompletionEvent;
91
92  public:
93    /** Constructs an LSQ unit. init() must be called prior to use. */
94    LSQUnit();
95
96    /** Initializes the LSQ unit with the specified number of entries. */
97    void init(Params *params, unsigned maxLQEntries,
98              unsigned maxSQEntries, unsigned id);
99
100    /** Returns the name of the LSQ unit. */
101    std::string name() const;
102
103    /** Sets the CPU pointer. */
104    void setCPU(FullCPU *cpu_ptr)
105    { cpu = cpu_ptr; }
106
107    /** Sets the IEW stage pointer. */
108    void setIEW(IEW *iew_ptr)
109    { iewStage = iew_ptr; }
110
111    /** Sets the page table pointer. */
112//    void setPageTable(PageTable *pt_ptr);
113
114    void switchOut();
115
116    void takeOverFrom();
117
118    bool isSwitchedOut() { return switchedOut; }
119
120    /** Ticks the LSQ unit, which in this case only resets the number of
121     * used cache ports.
122     * @todo: Move the number of used ports up to the LSQ level so it can
123     * be shared by all LSQ units.
124     */
125    void tick() { usedPorts = 0; }
126
127    /** Inserts an instruction. */
128    void insert(DynInstPtr &inst);
129    /** Inserts a load instruction. */
130    void insertLoad(DynInstPtr &load_inst);
131    /** Inserts a store instruction. */
132    void insertStore(DynInstPtr &store_inst);
133
134    /** Executes a load instruction. */
135    Fault executeLoad(DynInstPtr &inst);
136
137    Fault executeLoad(int lq_idx);
138    /** Executes a store instruction. */
139    Fault executeStore(DynInstPtr &inst);
140
141    /** Commits the head load. */
142    void commitLoad();
143    /** Commits a specific load, given by the sequence number. */
144    void commitLoad(InstSeqNum &inst);
145    /** Commits loads older than a specific sequence number. */
146    void commitLoads(InstSeqNum &youngest_inst);
147
148    /** Commits stores older than a specific sequence number. */
149    void commitStores(InstSeqNum &youngest_inst);
150
151    /** Writes back stores. */
152    void writebackStores();
153
154    // @todo: Include stats in the LSQ unit.
155    //void regStats();
156
157    /** Clears all the entries in the LQ. */
158    void clearLQ();
159
160    /** Clears all the entries in the SQ. */
161    void clearSQ();
162
163    /** Resizes the LQ to a given size. */
164    void resizeLQ(unsigned size);
165
166    /** Resizes the SQ to a given size. */
167    void resizeSQ(unsigned size);
168
169    /** Squashes all instructions younger than a specific sequence number. */
170    void squash(const InstSeqNum &squashed_num);
171
172    /** Returns if there is a memory ordering violation. Value is reset upon
173     * call to getMemDepViolator().
174     */
175    bool violation() { return memDepViolator; }
176
177    /** Returns the memory ordering violator. */
178    DynInstPtr getMemDepViolator();
179
180    /** Returns if a load became blocked due to the memory system.  It clears
181     *  the bool's value upon this being called.
182     */
183    bool loadBlocked()
184    { return isLoadBlocked; }
185
186    void clearLoadBlocked()
187    { isLoadBlocked = false; }
188
189    bool isLoadBlockedHandled()
190    { return loadBlockedHandled; }
191
192    void setLoadBlockedHandled()
193    { loadBlockedHandled = true; }
194
195    /** Returns the number of free entries (min of free LQ and SQ entries). */
196    unsigned numFreeEntries();
197
198    /** Returns the number of loads ready to execute. */
199    int numLoadsReady();
200
201    /** Returns the number of loads in the LQ. */
202    int numLoads() { return loads; }
203
204    /** Returns the number of stores in the SQ. */
205    int numStores() { return stores; }
206
207    /** Returns if either the LQ or SQ is full. */
208    bool isFull() { return lqFull() || sqFull(); }
209
210    /** Returns if the LQ is full. */
211    bool lqFull() { return loads >= (LQEntries - 1); }
212
213    /** Returns if the SQ is full. */
214    bool sqFull() { return stores >= (SQEntries - 1); }
215
216    /** Debugging function to dump instructions in the LSQ. */
217    void dumpInsts();
218
219    /** Returns the number of instructions in the LSQ. */
220    unsigned getCount() { return loads + stores; }
221
222    /** Returns if there are any stores to writeback. */
223    bool hasStoresToWB() { return storesToWB; }
224
225    /** Returns the number of stores to writeback. */
226    int numStoresToWB() { return storesToWB; }
227
228    /** Returns if the LSQ unit will writeback on this cycle. */
229    bool willWB() { return storeQueue[storeWBIdx].canWB &&
230                        !storeQueue[storeWBIdx].completed &&
231                        !dcacheInterface->isBlocked(); }
232
233  private:
234    /** Completes the store at the specified index. */
235    void completeStore(int store_idx);
236
237    /** Increments the given store index (circular queue). */
238    inline void incrStIdx(int &store_idx);
239    /** Decrements the given store index (circular queue). */
240    inline void decrStIdx(int &store_idx);
241    /** Increments the given load index (circular queue). */
242    inline void incrLdIdx(int &load_idx);
243    /** Decrements the given load index (circular queue). */
244    inline void decrLdIdx(int &load_idx);
245
246  private:
247    /** Pointer to the CPU. */
248    FullCPU *cpu;
249
250    /** Pointer to the IEW stage. */
251    IEW *iewStage;
252
253    /** Pointer to the D-cache. */
254    MemInterface *dcacheInterface;
255
256    /** Pointer to the page table. */
257//    PageTable *pTable;
258
259  public:
260    struct SQEntry {
261        /** Constructs an empty store queue entry. */
262        SQEntry()
263            : inst(NULL), req(NULL), size(0), data(0),
264              canWB(0), committed(0), completed(0)
265        { }
266
267        /** Constructs a store queue entry for a given instruction. */
268        SQEntry(DynInstPtr &_inst)
269            : inst(_inst), req(NULL), size(0), data(0),
270              canWB(0), committed(0), completed(0)
271        { }
272
273        /** The store instruction. */
274        DynInstPtr inst;
275        /** The memory request for the store. */
276        MemReqPtr req;
277        /** The size of the store. */
278        int size;
279        /** The store data. */
280        IntReg data;
281        /** Whether or not the store can writeback. */
282        bool canWB;
283        /** Whether or not the store is committed. */
284        bool committed;
285        /** Whether or not the store is completed. */
286        bool completed;
287    };
288/*
289    enum Status {
290        Running,
291        Idle,
292        DcacheMissStall,
293        DcacheMissSwitch
294    };
295*/
296  private:
297    /** The LSQUnit thread id. */
298    unsigned lsqID;
299
300    /** The status of the LSQ unit. */
301//    Status _status;
302
303    /** The store queue. */
304    std::vector<SQEntry> storeQueue;
305
306    /** The load queue. */
307    std::vector<DynInstPtr> loadQueue;
308
309    // Consider making these 16 bits
310    /** The number of LQ entries. */
311    unsigned LQEntries;
312    /** The number of SQ entries. */
313    unsigned SQEntries;
314
315    /** The number of load instructions in the LQ. */
316    int loads;
317    /** The number of store instructions in the SQ (excludes those waiting to
318     * writeback).
319     */
320    int stores;
321    /** The number of store instructions in the SQ waiting to writeback. */
322    int storesToWB;
323
324    /** The index of the head instruction in the LQ. */
325    int loadHead;
326    /** The index of the tail instruction in the LQ. */
327    int loadTail;
328
329    /** The index of the head instruction in the SQ. */
330    int storeHead;
331    /** The index of the first instruction that is ready to be written back,
332     * and has not yet been written back.
333     */
334    int storeWBIdx;
335    /** The index of the tail instruction in the SQ. */
336    int storeTail;
337
338    /// @todo Consider moving to a more advanced model with write vs read ports
339    /** The number of cache ports available each cycle. */
340    int cachePorts;
341
342    /** The number of used cache ports in this cycle. */
343    int usedPorts;
344
345    bool switchedOut;
346
347    //list<InstSeqNum> mshrSeqNums;
348
349     //Stats::Scalar<> dcacheStallCycles;
350    Counter lastDcacheStall;
351
352    /** Wire to read information from the issue stage time queue. */
353    typename TimeBuffer<IssueStruct>::wire fromIssue;
354
355    // Make these per thread?
356    /** Whether or not the LSQ is stalled. */
357    bool stalled;
358    /** The store that causes the stall due to partial store to load
359     * forwarding.
360     */
361    InstSeqNum stallingStoreIsn;
362    /** The index of the above store. */
363    int stallingLoadIdx;
364
365    /** Whether or not a load is blocked due to the memory system.  It is
366     *  cleared when this value is checked via loadBlocked().
367     */
368    bool isLoadBlocked;
369
370    bool loadBlockedHandled;
371
372    InstSeqNum blockedLoadSeqNum;
373
374    /** The oldest faulting load instruction. */
375    DynInstPtr loadFaultInst;
376    /** The oldest faulting store instruction. */
377    DynInstPtr storeFaultInst;
378
379    /** The oldest load that caused a memory ordering violation. */
380    DynInstPtr memDepViolator;
381
382    // Will also need how many read/write ports the Dcache has.  Or keep track
383    // of that in stage that is one level up, and only call executeLoad/Store
384    // the appropriate number of times.
385/*
386    // total number of loads forwaded from LSQ stores
387    Stats::Vector<> lsq_forw_loads;
388
389    // total number of loads ignored due to invalid addresses
390    Stats::Vector<> inv_addr_loads;
391
392    // total number of software prefetches ignored due to invalid addresses
393    Stats::Vector<> inv_addr_swpfs;
394
395    // total non-speculative bogus addresses seen (debug var)
396    Counter sim_invalid_addrs;
397    Stats::Vector<> fu_busy;  //cumulative fu busy
398
399    // ready loads blocked due to memory disambiguation
400    Stats::Vector<> lsq_blocked_loads;
401
402    Stats::Scalar<> lsqInversion;
403*/
404  public:
405    /** Executes the load at the given index. */
406    template <class T>
407    Fault read(MemReqPtr &req, T &data, int load_idx);
408
409    /** Executes the store at the given index. */
410    template <class T>
411    Fault write(MemReqPtr &req, T &data, int store_idx);
412
413    /** Returns the index of the head load instruction. */
414    int getLoadHead() { return loadHead; }
415    /** Returns the sequence number of the head load instruction. */
416    InstSeqNum getLoadHeadSeqNum()
417    {
418        if (loadQueue[loadHead]) {
419            return loadQueue[loadHead]->seqNum;
420        } else {
421            return 0;
422        }
423
424    }
425
426    /** Returns the index of the head store instruction. */
427    int getStoreHead() { return storeHead; }
428    /** Returns the sequence number of the head store instruction. */
429    InstSeqNum getStoreHeadSeqNum()
430    {
431        if (storeQueue[storeHead].inst) {
432            return storeQueue[storeHead].inst->seqNum;
433        } else {
434            return 0;
435        }
436
437    }
438
439    /** Returns whether or not the LSQ unit is stalled. */
440    bool isStalled()  { return stalled; }
441};
442
443template <class Impl>
444template <class T>
445Fault
446LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx)
447{
448    //Depending on issue2execute delay a squashed load could
449    //execute if it is found to be squashed in the same
450    //cycle it is scheduled to execute
451    assert(loadQueue[load_idx]);
452
453    if (loadQueue[load_idx]->isExecuted()) {
454        panic("Should not reach this point with split ops!");
455        memcpy(&data,req->data,req->size);
456
457        return NoFault;
458    }
459
460    // Make sure this isn't an uncacheable access
461    // A bit of a hackish way to get uncached accesses to work only if they're
462    // at the head of the LSQ and are ready to commit (at the head of the ROB
463    // too).
464    // @todo: Fix uncached accesses.
465    if (req->flags & UNCACHEABLE &&
466        (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) {
467        iewStage->rescheduleMemInst(loadQueue[load_idx]);
468        return TheISA::genMachineCheckFault();
469    }
470
471    // Check the SQ for any previous stores that might lead to forwarding
472    int store_idx = loadQueue[load_idx]->sqIdx;
473
474    int store_size = 0;
475
476    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
477            "storeHead: %i addr: %#x\n",
478            load_idx, store_idx, storeHead, req->paddr);
479
480#ifdef FULL_SYSTEM
481    if (req->flags & LOCKED) {
482        cpu->lockAddr = req->paddr;
483        cpu->lockFlag = true;
484    }
485#endif
486
487    while (store_idx != -1) {
488        // End once we've reached the top of the LSQ
489        if (store_idx == storeWBIdx) {
490            break;
491        }
492
493        // Move the index to one younger
494        if (--store_idx < 0)
495            store_idx += SQEntries;
496
497        assert(storeQueue[store_idx].inst);
498
499        store_size = storeQueue[store_idx].size;
500
501        if (store_size == 0)
502            continue;
503
504        // Check if the store data is within the lower and upper bounds of
505        // addresses that the request needs.
506        bool store_has_lower_limit =
507            req->vaddr >= storeQueue[store_idx].inst->effAddr;
508        bool store_has_upper_limit =
509            (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr +
510                                         store_size);
511        bool lower_load_has_store_part =
512            req->vaddr < (storeQueue[store_idx].inst->effAddr +
513                           store_size);
514        bool upper_load_has_store_part =
515            (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr;
516
517        // If the store's data has all of the data needed, we can forward.
518        if (store_has_lower_limit && store_has_upper_limit) {
519
520            int shift_amt = req->vaddr & (store_size - 1);
521            // Assumes byte addressing
522            shift_amt = shift_amt << 3;
523
524            // Cast this to type T?
525            data = storeQueue[store_idx].data >> shift_amt;
526
527            req->cmd = Read;
528            assert(!req->completionEvent);
529            req->completionEvent = NULL;
530            req->time = curTick;
531            assert(!req->data);
532            req->data = new uint8_t[64];
533
534            memcpy(req->data, &data, req->size);
535
536            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
537                    "addr %#x, data %#x\n",
538                    store_idx, req->vaddr, *(req->data));
539
540            typename IEW::LdWritebackEvent *wb =
541                new typename IEW::LdWritebackEvent(loadQueue[load_idx],
542                                                   iewStage);
543
544            // We'll say this has a 1 cycle load-store forwarding latency
545            // for now.
546            // @todo: Need to make this a parameter.
547            wb->schedule(curTick);
548
549            // Should keep track of stat for forwarded data
550            return NoFault;
551        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
552                   (store_has_upper_limit && upper_load_has_store_part) ||
553                   (lower_load_has_store_part && upper_load_has_store_part)) {
554            // This is the partial store-load forwarding case where a store
555            // has only part of the load's data.
556
557            // If it's already been written back, then don't worry about
558            // stalling on it.
559            if (storeQueue[store_idx].completed) {
560                continue;
561            }
562
563            // Must stall load and force it to retry, so long as it's the oldest
564            // load that needs to do so.
565            if (!stalled ||
566                (stalled &&
567                 loadQueue[load_idx]->seqNum <
568                 loadQueue[stallingLoadIdx]->seqNum)) {
569                stalled = true;
570                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
571                stallingLoadIdx = load_idx;
572            }
573
574            // Tell IQ/mem dep unit that this instruction will need to be
575            // rescheduled eventually
576            iewStage->rescheduleMemInst(loadQueue[load_idx]);
577
578            // Do not generate a writeback event as this instruction is not
579            // complete.
580
581            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
582                    "Store idx %i to load addr %#x\n",
583                    store_idx, req->vaddr);
584
585            return NoFault;
586        }
587    }
588
589
590    // If there's no forwarding case, then go access memory
591    DynInstPtr inst = loadQueue[load_idx];
592
593    DPRINTF(LSQUnit, "Doing functional access for inst PC %#x\n",
594            loadQueue[load_idx]->readPC());
595    assert(!req->data);
596    req->cmd = Read;
597    req->completionEvent = NULL;
598    req->time = curTick;
599    req->data = new uint8_t[64];
600    Fault fault = cpu->read(req, data);
601    memcpy(req->data, &data, sizeof(T));
602
603    ++usedPorts;
604
605    // if we have a cache, do cache access too
606    if (fault == NoFault && dcacheInterface) {
607        if (dcacheInterface->isBlocked()) {
608            // There's an older load that's already going to squash.
609            if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
610                return NoFault;
611
612            isLoadBlocked = true;
613            loadBlockedHandled = false;
614            blockedLoadSeqNum = inst->seqNum;
615            // No fault occurred, even though the interface is blocked.
616            return NoFault;
617        }
618        DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
619                loadQueue[load_idx]->readPC());
620/*
621        Addr debug_addr = ULL(0xfffffc0000be81a8);
622        if (req->vaddr == debug_addr) {
623            debug_break();
624        }
625*/
626        assert(!req->completionEvent);
627        req->completionEvent =
628            new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
629        MemAccessResult result = dcacheInterface->access(req);
630
631        assert(dcacheInterface->doEvents());
632
633        // Ugly hack to get an event scheduled *only* if the access is
634        // a miss.  We really should add first-class support for this
635        // at some point.
636        if (result != MA_HIT) {
637            DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
638            DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
639                    inst->seqNum);
640
641            lastDcacheStall = curTick;
642
643//            _status = DcacheMissStall;
644
645        } else {
646            DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
647                    inst->seqNum);
648
649            DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
650        }
651    }
652#if 0
653    // if we have a cache, do cache access too
654    if (dcacheInterface) {
655        if (dcacheInterface->isBlocked()) {
656            isLoadBlocked = true;
657            // No fault occurred, even though the interface is blocked.
658            return NoFault;
659        }
660
661        DPRINTF(LSQUnit, "LSQUnit: D-cache: PC:%#x reading from paddr:%#x "
662                "vaddr:%#x flags:%i\n",
663                inst->readPC(), req->paddr, req->vaddr, req->flags);
664
665        // Setup MemReq pointer
666        req->cmd = Read;
667        req->completionEvent = NULL;
668        req->time = curTick;
669        assert(!req->data);
670        req->data = new uint8_t[64];
671
672        assert(!req->completionEvent);
673        req->completionEvent =
674            new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage);
675
676        // Do Cache Access
677        MemAccessResult result = dcacheInterface->access(req);
678
679        // Ugly hack to get an event scheduled *only* if the access is
680        // a miss.  We really should add first-class support for this
681        // at some point.
682        // @todo: Probably should support having no events
683        if (result != MA_HIT) {
684            DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
685            DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
686                    inst->seqNum);
687
688            lastDcacheStall = curTick;
689
690            _status = DcacheMissStall;
691
692        } else {
693            DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
694                    inst->seqNum);
695
696            DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
697        }
698    } else {
699        fatal("Must use D-cache with new memory system");
700    }
701#endif
702
703    return fault;
704}
705
706template <class Impl>
707template <class T>
708Fault
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