lsq_unit.hh revision 4332:548ef28989b8
1/*
2 * Copyright (c) 2004-2006 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 * Authors: Kevin Lim
29 *          Korey Sewell
30 */
31
32#ifndef __CPU_O3_LSQ_UNIT_HH__
33#define __CPU_O3_LSQ_UNIT_HH__
34
35#include <algorithm>
36#include <map>
37#include <queue>
38
39#include "arch/faults.hh"
40#include "arch/locked_mem.hh"
41#include "config/full_system.hh"
42#include "base/hashmap.hh"
43#include "cpu/inst_seq.hh"
44#include "mem/packet.hh"
45#include "mem/port.hh"
46
47/**
48 * Class that implements the actual LQ and SQ for each specific
49 * thread.  Both are circular queues; load entries are freed upon
50 * committing, while store entries are freed once they writeback. The
51 * LSQUnit tracks if there are memory ordering violations, and also
52 * detects partial load to store forwarding cases (a store only has
53 * part of a load's data) that requires the load to wait until the
54 * store writes back. In the former case it holds onto the instruction
55 * until the dependence unit looks at it, and in the latter it stalls
56 * the LSQ until the store writes back. At that point the load is
57 * replayed.
58 */
59template <class Impl>
60class LSQUnit {
61  protected:
62    typedef TheISA::IntReg IntReg;
63  public:
64    typedef typename Impl::Params Params;
65    typedef typename Impl::O3CPU O3CPU;
66    typedef typename Impl::DynInstPtr DynInstPtr;
67    typedef typename Impl::CPUPol::IEW IEW;
68    typedef typename Impl::CPUPol::LSQ LSQ;
69    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
70
71  public:
72    /** Constructs an LSQ unit. init() must be called prior to use. */
73    LSQUnit();
74
75    /** Initializes the LSQ unit with the specified number of entries. */
76    void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
77              unsigned maxLQEntries, unsigned maxSQEntries, unsigned id);
78
79    /** Returns the name of the LSQ unit. */
80    std::string name() const;
81
82    /** Registers statistics. */
83    void regStats();
84
85    /** Sets the pointer to the dcache port. */
86    void setDcachePort(Port *dcache_port);
87
88    /** Switches out LSQ unit. */
89    void switchOut();
90
91    /** Takes over from another CPU's thread. */
92    void takeOverFrom();
93
94    /** Returns if the LSQ is switched out. */
95    bool isSwitchedOut() { return switchedOut; }
96
97    /** Ticks the LSQ unit, which in this case only resets the number of
98     * used cache ports.
99     * @todo: Move the number of used ports up to the LSQ level so it can
100     * be shared by all LSQ units.
101     */
102    void tick() { usedPorts = 0; }
103
104    /** Inserts an instruction. */
105    void insert(DynInstPtr &inst);
106    /** Inserts a load instruction. */
107    void insertLoad(DynInstPtr &load_inst);
108    /** Inserts a store instruction. */
109    void insertStore(DynInstPtr &store_inst);
110
111    /** Executes a load instruction. */
112    Fault executeLoad(DynInstPtr &inst);
113
114    Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
115    /** Executes a store instruction. */
116    Fault executeStore(DynInstPtr &inst);
117
118    /** Commits the head load. */
119    void commitLoad();
120    /** Commits loads older than a specific sequence number. */
121    void commitLoads(InstSeqNum &youngest_inst);
122
123    /** Commits stores older than a specific sequence number. */
124    void commitStores(InstSeqNum &youngest_inst);
125
126    /** Writes back stores. */
127    void writebackStores();
128
129    /** Completes the data access that has been returned from the
130     * memory system. */
131    void completeDataAccess(PacketPtr pkt);
132
133    /** Clears all the entries in the LQ. */
134    void clearLQ();
135
136    /** Clears all the entries in the SQ. */
137    void clearSQ();
138
139    /** Resizes the LQ to a given size. */
140    void resizeLQ(unsigned size);
141
142    /** Resizes the SQ to a given size. */
143    void resizeSQ(unsigned size);
144
145    /** Squashes all instructions younger than a specific sequence number. */
146    void squash(const InstSeqNum &squashed_num);
147
148    /** Returns if there is a memory ordering violation. Value is reset upon
149     * call to getMemDepViolator().
150     */
151    bool violation() { return memDepViolator; }
152
153    /** Returns the memory ordering violator. */
154    DynInstPtr getMemDepViolator();
155
156    /** Returns if a load became blocked due to the memory system. */
157    bool loadBlocked()
158    { return isLoadBlocked; }
159
160    /** Clears the signal that a load became blocked. */
161    void clearLoadBlocked()
162    { isLoadBlocked = false; }
163
164    /** Returns if the blocked load was handled. */
165    bool isLoadBlockedHandled()
166    { return loadBlockedHandled; }
167
168    /** Records the blocked load as being handled. */
169    void setLoadBlockedHandled()
170    { loadBlockedHandled = true; }
171
172    /** Returns the number of free entries (min of free LQ and SQ entries). */
173    unsigned numFreeEntries();
174
175    /** Returns the number of loads ready to execute. */
176    int numLoadsReady();
177
178    /** Returns the number of loads in the LQ. */
179    int numLoads() { return loads; }
180
181    /** Returns the number of stores in the SQ. */
182    int numStores() { return stores; }
183
184    /** Returns if either the LQ or SQ is full. */
185    bool isFull() { return lqFull() || sqFull(); }
186
187    /** Returns if the LQ is full. */
188    bool lqFull() { return loads >= (LQEntries - 1); }
189
190    /** Returns if the SQ is full. */
191    bool sqFull() { return stores >= (SQEntries - 1); }
192
193    /** Returns the number of instructions in the LSQ. */
194    unsigned getCount() { return loads + stores; }
195
196    /** Returns if there are any stores to writeback. */
197    bool hasStoresToWB() { return storesToWB; }
198
199    /** Returns the number of stores to writeback. */
200    int numStoresToWB() { return storesToWB; }
201
202    /** Returns if the LSQ unit will writeback on this cycle. */
203    bool willWB() { return storeQueue[storeWBIdx].canWB &&
204                        !storeQueue[storeWBIdx].completed &&
205                        !isStoreBlocked; }
206
207    /** Handles doing the retry. */
208    void recvRetry();
209
210  private:
211    /** Writes back the instruction, sending it to IEW. */
212    void writeback(DynInstPtr &inst, PacketPtr pkt);
213
214    /** Handles completing the send of a store to memory. */
215    void storePostSend(PacketPtr pkt);
216
217    /** Completes the store at the specified index. */
218    void completeStore(int store_idx);
219
220    /** Increments the given store index (circular queue). */
221    inline void incrStIdx(int &store_idx);
222    /** Decrements the given store index (circular queue). */
223    inline void decrStIdx(int &store_idx);
224    /** Increments the given load index (circular queue). */
225    inline void incrLdIdx(int &load_idx);
226    /** Decrements the given load index (circular queue). */
227    inline void decrLdIdx(int &load_idx);
228
229  public:
230    /** Debugging function to dump instructions in the LSQ. */
231    void dumpInsts();
232
233  private:
234    /** Pointer to the CPU. */
235    O3CPU *cpu;
236
237    /** Pointer to the IEW stage. */
238    IEW *iewStage;
239
240    /** Pointer to the LSQ. */
241    LSQ *lsq;
242
243    /** Pointer to the dcache port.  Used only for sending. */
244    Port *dcachePort;
245
246    /** Derived class to hold any sender state the LSQ needs. */
247    class LSQSenderState : public Packet::SenderState
248    {
249      public:
250        /** Default constructor. */
251        LSQSenderState()
252            : noWB(false)
253        { }
254
255        /** Instruction who initiated the access to memory. */
256        DynInstPtr inst;
257        /** Whether or not it is a load. */
258        bool isLoad;
259        /** The LQ/SQ index of the instruction. */
260        int idx;
261        /** Whether or not the instruction will need to writeback. */
262        bool noWB;
263    };
264
265    /** Writeback event, specifically for when stores forward data to loads. */
266    class WritebackEvent : public Event {
267      public:
268        /** Constructs a writeback event. */
269        WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr);
270
271        /** Processes the writeback event. */
272        void process();
273
274        /** Returns the description of this event. */
275        const char *description();
276
277      private:
278        /** Instruction whose results are being written back. */
279        DynInstPtr inst;
280
281        /** The packet that would have been sent to memory. */
282        PacketPtr pkt;
283
284        /** The pointer to the LSQ unit that issued the store. */
285        LSQUnit<Impl> *lsqPtr;
286    };
287
288  public:
289    struct SQEntry {
290        /** Constructs an empty store queue entry. */
291        SQEntry()
292            : inst(NULL), req(NULL), size(0),
293              canWB(0), committed(0), completed(0)
294        {
295            bzero(data, sizeof(data));
296        }
297
298        /** Constructs a store queue entry for a given instruction. */
299        SQEntry(DynInstPtr &_inst)
300            : inst(_inst), req(NULL), size(0),
301              canWB(0), committed(0), completed(0)
302        {
303            bzero(data, sizeof(data));
304        }
305
306        /** The store instruction. */
307        DynInstPtr inst;
308        /** The request for the store. */
309        RequestPtr req;
310        /** The size of the store. */
311        int size;
312        /** The store data. */
313        char data[sizeof(IntReg)];
314        /** Whether or not the store can writeback. */
315        bool canWB;
316        /** Whether or not the store is committed. */
317        bool committed;
318        /** Whether or not the store is completed. */
319        bool completed;
320    };
321
322  private:
323    /** The LSQUnit thread id. */
324    unsigned lsqID;
325
326    /** The store queue. */
327    std::vector<SQEntry> storeQueue;
328
329    /** The load queue. */
330    std::vector<DynInstPtr> loadQueue;
331
332    /** The number of LQ entries, plus a sentinel entry (circular queue).
333     *  @todo: Consider having var that records the true number of LQ entries.
334     */
335    unsigned LQEntries;
336    /** The number of SQ entries, plus a sentinel entry (circular queue).
337     *  @todo: Consider having var that records the true number of SQ entries.
338     */
339    unsigned SQEntries;
340
341    /** The number of load instructions in the LQ. */
342    int loads;
343    /** The number of store instructions in the SQ. */
344    int stores;
345    /** The number of store instructions in the SQ waiting to writeback. */
346    int storesToWB;
347
348    /** The index of the head instruction in the LQ. */
349    int loadHead;
350    /** The index of the tail instruction in the LQ. */
351    int loadTail;
352
353    /** The index of the head instruction in the SQ. */
354    int storeHead;
355    /** The index of the first instruction that may be ready to be
356     * written back, and has not yet been written back.
357     */
358    int storeWBIdx;
359    /** The index of the tail instruction in the SQ. */
360    int storeTail;
361
362    /// @todo Consider moving to a more advanced model with write vs read ports
363    /** The number of cache ports available each cycle. */
364    int cachePorts;
365
366    /** The number of used cache ports in this cycle. */
367    int usedPorts;
368
369    /** Is the LSQ switched out. */
370    bool switchedOut;
371
372    //list<InstSeqNum> mshrSeqNums;
373
374    /** Wire to read information from the issue stage time queue. */
375    typename TimeBuffer<IssueStruct>::wire fromIssue;
376
377    /** Whether or not the LSQ is stalled. */
378    bool stalled;
379    /** The store that causes the stall due to partial store to load
380     * forwarding.
381     */
382    InstSeqNum stallingStoreIsn;
383    /** The index of the above store. */
384    int stallingLoadIdx;
385
386    /** The packet that needs to be retried. */
387    PacketPtr retryPkt;
388
389    /** Whehter or not a store is blocked due to the memory system. */
390    bool isStoreBlocked;
391
392    /** Whether or not a load is blocked due to the memory system. */
393    bool isLoadBlocked;
394
395    /** Has the blocked load been handled. */
396    bool loadBlockedHandled;
397
398    /** The sequence number of the blocked load. */
399    InstSeqNum blockedLoadSeqNum;
400
401    /** The oldest load that caused a memory ordering violation. */
402    DynInstPtr memDepViolator;
403
404    // Will also need how many read/write ports the Dcache has.  Or keep track
405    // of that in stage that is one level up, and only call executeLoad/Store
406    // the appropriate number of times.
407    /** Total number of loads forwaded from LSQ stores. */
408    Stats::Scalar<> lsqForwLoads;
409
410    /** Total number of loads ignored due to invalid addresses. */
411    Stats::Scalar<> invAddrLoads;
412
413    /** Total number of squashed loads. */
414    Stats::Scalar<> lsqSquashedLoads;
415
416    /** Total number of responses from the memory system that are
417     * ignored due to the instruction already being squashed. */
418    Stats::Scalar<> lsqIgnoredResponses;
419
420    /** Tota number of memory ordering violations. */
421    Stats::Scalar<> lsqMemOrderViolation;
422
423    /** Total number of squashed stores. */
424    Stats::Scalar<> lsqSquashedStores;
425
426    /** Total number of software prefetches ignored due to invalid addresses. */
427    Stats::Scalar<> invAddrSwpfs;
428
429    /** Ready loads blocked due to partial store-forwarding. */
430    Stats::Scalar<> lsqBlockedLoads;
431
432    /** Number of loads that were rescheduled. */
433    Stats::Scalar<> lsqRescheduledLoads;
434
435    /** Number of times the LSQ is blocked due to the cache. */
436    Stats::Scalar<> lsqCacheBlocked;
437
438  public:
439    /** Executes the load at the given index. */
440    template <class T>
441    Fault read(Request *req, T &data, int load_idx);
442
443    /** Executes the store at the given index. */
444    template <class T>
445    Fault write(Request *req, T &data, int store_idx);
446
447    /** Returns the index of the head load instruction. */
448    int getLoadHead() { return loadHead; }
449    /** Returns the sequence number of the head load instruction. */
450    InstSeqNum getLoadHeadSeqNum()
451    {
452        if (loadQueue[loadHead]) {
453            return loadQueue[loadHead]->seqNum;
454        } else {
455            return 0;
456        }
457
458    }
459
460    /** Returns the index of the head store instruction. */
461    int getStoreHead() { return storeHead; }
462    /** Returns the sequence number of the head store instruction. */
463    InstSeqNum getStoreHeadSeqNum()
464    {
465        if (storeQueue[storeHead].inst) {
466            return storeQueue[storeHead].inst->seqNum;
467        } else {
468            return 0;
469        }
470
471    }
472
473    /** Returns whether or not the LSQ unit is stalled. */
474    bool isStalled()  { return stalled; }
475};
476
477template <class Impl>
478template <class T>
479Fault
480LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
481{
482    DynInstPtr load_inst = loadQueue[load_idx];
483
484    assert(load_inst);
485
486    assert(!load_inst->isExecuted());
487
488    // Make sure this isn't an uncacheable access
489    // A bit of a hackish way to get uncached accesses to work only if they're
490    // at the head of the LSQ and are ready to commit (at the head of the ROB
491    // too).
492    if (req->isUncacheable() &&
493        (load_idx != loadHead || !load_inst->isAtCommit())) {
494        iewStage->rescheduleMemInst(load_inst);
495        ++lsqRescheduledLoads;
496
497        // Must delete request now that it wasn't handed off to
498        // memory.  This is quite ugly.  @todo: Figure out the proper
499        // place to really handle request deletes.
500        delete req;
501        return TheISA::genMachineCheckFault();
502    }
503
504    // Check the SQ for any previous stores that might lead to forwarding
505    int store_idx = load_inst->sqIdx;
506
507    int store_size = 0;
508
509    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
510            "storeHead: %i addr: %#x\n",
511            load_idx, store_idx, storeHead, req->getPaddr());
512
513    if (req->isLocked()) {
514        // Disable recording the result temporarily.  Writing to misc
515        // regs normally updates the result, but this is not the
516        // desired behavior when handling store conditionals.
517        load_inst->recordResult = false;
518        TheISA::handleLockedRead(load_inst.get(), req);
519        load_inst->recordResult = true;
520    }
521
522    while (store_idx != -1) {
523        // End once we've reached the top of the LSQ
524        if (store_idx == storeWBIdx) {
525            break;
526        }
527
528        // Move the index to one younger
529        if (--store_idx < 0)
530            store_idx += SQEntries;
531
532        assert(storeQueue[store_idx].inst);
533
534        store_size = storeQueue[store_idx].size;
535
536        if (store_size == 0)
537            continue;
538        else if (storeQueue[store_idx].inst->uncacheable())
539            continue;
540
541        assert(storeQueue[store_idx].inst->effAddrValid);
542
543        // Check if the store data is within the lower and upper bounds of
544        // addresses that the request needs.
545        bool store_has_lower_limit =
546            req->getVaddr() >= storeQueue[store_idx].inst->effAddr;
547        bool store_has_upper_limit =
548            (req->getVaddr() + req->getSize()) <=
549            (storeQueue[store_idx].inst->effAddr + store_size);
550        bool lower_load_has_store_part =
551            req->getVaddr() < (storeQueue[store_idx].inst->effAddr +
552                           store_size);
553        bool upper_load_has_store_part =
554            (req->getVaddr() + req->getSize()) >
555            storeQueue[store_idx].inst->effAddr;
556
557        // If the store's data has all of the data needed, we can forward.
558        if ((store_has_lower_limit && store_has_upper_limit)) {
559            // Get shift amount for offset into the store's data.
560            int shift_amt = req->getVaddr() & (store_size - 1);
561
562            memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
563
564            assert(!load_inst->memData);
565            load_inst->memData = new uint8_t[64];
566
567            memcpy(load_inst->memData,
568                    storeQueue[store_idx].data + shift_amt, req->getSize());
569
570            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
571                    "addr %#x, data %#x\n",
572                    store_idx, req->getVaddr(), data);
573
574            PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq,
575                                            Packet::Broadcast);
576            data_pkt->dataStatic(load_inst->memData);
577
578            WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this);
579
580            // We'll say this has a 1 cycle load-store forwarding latency
581            // for now.
582            // @todo: Need to make this a parameter.
583            wb->schedule(curTick);
584
585            ++lsqForwLoads;
586            return NoFault;
587        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
588                   (store_has_upper_limit && upper_load_has_store_part) ||
589                   (lower_load_has_store_part && upper_load_has_store_part)) {
590            // This is the partial store-load forwarding case where a store
591            // has only part of the load's data.
592
593            // If it's already been written back, then don't worry about
594            // stalling on it.
595            if (storeQueue[store_idx].completed) {
596                panic("Should not check one of these");
597                continue;
598            }
599
600            // Must stall load and force it to retry, so long as it's the oldest
601            // load that needs to do so.
602            if (!stalled ||
603                (stalled &&
604                 load_inst->seqNum <
605                 loadQueue[stallingLoadIdx]->seqNum)) {
606                stalled = true;
607                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
608                stallingLoadIdx = load_idx;
609            }
610
611            // Tell IQ/mem dep unit that this instruction will need to be
612            // rescheduled eventually
613            iewStage->rescheduleMemInst(load_inst);
614            iewStage->decrWb(load_inst->seqNum);
615            load_inst->clearIssued();
616            ++lsqRescheduledLoads;
617
618            // Do not generate a writeback event as this instruction is not
619            // complete.
620            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
621                    "Store idx %i to load addr %#x\n",
622                    store_idx, req->getVaddr());
623
624            // Must delete request now that it wasn't handed off to
625            // memory.  This is quite ugly.  @todo: Figure out the
626            // proper place to really handle request deletes.
627            delete req;
628
629            return NoFault;
630        }
631    }
632
633    // If there's no forwarding case, then go access memory
634    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
635            load_inst->seqNum, load_inst->readPC());
636
637    assert(!load_inst->memData);
638    load_inst->memData = new uint8_t[64];
639
640    ++usedPorts;
641
642    // if we the cache is not blocked, do cache access
643    if (!lsq->cacheBlocked()) {
644        PacketPtr data_pkt =
645            new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
646        data_pkt->dataStatic(load_inst->memData);
647
648        LSQSenderState *state = new LSQSenderState;
649        state->isLoad = true;
650        state->idx = load_idx;
651        state->inst = load_inst;
652        data_pkt->senderState = state;
653
654        if (!dcachePort->sendTiming(data_pkt)) {
655            Packet::Result result = data_pkt->result;
656
657            // Delete state and data packet because a load retry
658            // initiates a pipeline restart; it does not retry.
659            delete state;
660            delete data_pkt->req;
661            delete data_pkt;
662
663            req = NULL;
664
665            if (result == Packet::BadAddress) {
666                return TheISA::genMachineCheckFault();
667            }
668
669            // If the access didn't succeed, tell the LSQ by setting
670            // the retry thread id.
671            lsq->setRetryTid(lsqID);
672        }
673    }
674
675    // If the cache was blocked, or has become blocked due to the access,
676    // handle it.
677    if (lsq->cacheBlocked()) {
678        if (req)
679            delete req;
680
681        ++lsqCacheBlocked;
682
683        iewStage->decrWb(load_inst->seqNum);
684        // There's an older load that's already going to squash.
685        if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
686            return NoFault;
687
688        // Record that the load was blocked due to memory.  This
689        // load will squash all instructions after it, be
690        // refetched, and re-executed.
691        isLoadBlocked = true;
692        loadBlockedHandled = false;
693        blockedLoadSeqNum = load_inst->seqNum;
694        // No fault occurred, even though the interface is blocked.
695        return NoFault;
696    }
697
698    return NoFault;
699}
700
701template <class Impl>
702template <class T>
703Fault
704LSQUnit<Impl>::write(Request *req, T &data, int store_idx)
705{
706    assert(storeQueue[store_idx].inst);
707
708    DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
709            " | storeHead:%i [sn:%i]\n",
710            store_idx, req->getPaddr(), data, storeHead,
711            storeQueue[store_idx].inst->seqNum);
712
713    storeQueue[store_idx].req = req;
714    storeQueue[store_idx].size = sizeof(T);
715    assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
716
717    T gData = htog(data);
718    memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
719
720    // This function only writes the data to the store queue, so no fault
721    // can happen here.
722    return NoFault;
723}
724
725#endif // __CPU_O3_LSQ_UNIT_HH__
726