mem_dep_unit_impl.hh revision 10510
18713Sandreas.hansson@arm.com/*
27586SAli.Saidi@arm.com * Copyright (c) 2012, 2014 ARM Limited
37586SAli.Saidi@arm.com * All rights reserved
47586SAli.Saidi@arm.com *
57586SAli.Saidi@arm.com * The license below extends only to copyright in the software and shall
67586SAli.Saidi@arm.com * not be construed as granting a license to any other intellectual
77586SAli.Saidi@arm.com * property including but not limited to intellectual property relating
87586SAli.Saidi@arm.com * to a hardware implementation of the functionality of the software
97586SAli.Saidi@arm.com * licensed hereunder.  You may use the software subject to the license
107586SAli.Saidi@arm.com * terms below provided that you ensure that this notice is replicated
117586SAli.Saidi@arm.com * unmodified and in its entirety in all distributions of the software,
127586SAli.Saidi@arm.com * modified or unmodified, in source code or in binary form.
133970Sgblack@eecs.umich.edu *
143005Sstever@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan
153005Sstever@eecs.umich.edu * All rights reserved.
163005Sstever@eecs.umich.edu *
173005Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
183005Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are
193005Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright
203005Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
213005Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
223005Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
233005Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
243005Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
253005Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
263005Sstever@eecs.umich.edu * this software without specific prior written permission.
273005Sstever@eecs.umich.edu *
283005Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293005Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303005Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
313005Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
323005Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333005Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
343005Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
353005Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363005Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
373005Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
383005Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
393005Sstever@eecs.umich.edu *
403005Sstever@eecs.umich.edu * Authors: Kevin Lim
416654Snate@binkert.org */
426654Snate@binkert.org
436654Snate@binkert.org#ifndef __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
442889SN/A#define __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
452710SN/A
466654Snate@binkert.org#include <map>
476654Snate@binkert.org
486654Snate@binkert.org#include "cpu/o3/inst_queue.hh"
495457Ssaidi@eecs.umich.edu#include "cpu/o3/mem_dep_unit.hh"
506654Snate@binkert.org#include "debug/MemDepUnit.hh"
516654Snate@binkert.org#include "params/DerivO3CPU.hh"
525457Ssaidi@eecs.umich.edu
536654Snate@binkert.orgtemplate <class MemDepPred, class Impl>
546654Snate@binkert.orgMemDepUnit<MemDepPred, Impl>::MemDepUnit()
552934SN/A    : loadBarrier(false), loadBarrierSN(0), storeBarrier(false),
562549SN/A      storeBarrierSN(0), iqPtr(NULL)
572995SN/A{
583395Shsul@eecs.umich.edu}
596981SLisa.Hsu@amd.com
603448Shsul@eecs.umich.edutemplate <class MemDepPred, class Impl>
612549SN/AMemDepUnit<MemDepPred, Impl>::MemDepUnit(DerivO3CPUParams *params)
623444Sktlim@umich.edu    : _name(params->name + ".memdepunit"),
633444Sktlim@umich.edu      depPred(params->store_set_clear_period, params->SSITSize,
643444Sktlim@umich.edu              params->LFSTSize),
653444Sktlim@umich.edu      loadBarrier(false), loadBarrierSN(0), storeBarrier(false),
662889SN/A      storeBarrierSN(0), iqPtr(NULL)
672710SN/A{
687861Sgblack@eecs.umich.edu    DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");
697861Sgblack@eecs.umich.edu}
707861Sgblack@eecs.umich.edu
717861Sgblack@eecs.umich.edutemplate <class MemDepPred, class Impl>
723873Sbinkertn@umich.eduMemDepUnit<MemDepPred, Impl>::~MemDepUnit()
733873Sbinkertn@umich.edu{
743873Sbinkertn@umich.edu    for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
758635Schris.emmons@arm.com
768635Schris.emmons@arm.com        ListIt inst_list_it = instList[tid].begin();
778635Schris.emmons@arm.com
788635Schris.emmons@arm.com        MemDepHashIt hash_it;
797586SAli.Saidi@arm.com
807586SAli.Saidi@arm.com        while (!instList[tid].empty()) {
817586SAli.Saidi@arm.com            hash_it = memDepHash.find((*inst_list_it)->seqNum);
827586SAli.Saidi@arm.com
837586SAli.Saidi@arm.com            assert(hash_it != memDepHash.end());
843322Shsul@eecs.umich.edu
852995SN/A            memDepHash.erase(hash_it);
862995SN/A
872995SN/A            instList[tid].erase(inst_list_it++);
882995SN/A        }
892995SN/A    }
903143Shsul@eecs.umich.edu
913322Shsul@eecs.umich.edu#ifdef DEBUG
923322Shsul@eecs.umich.edu    assert(MemDepEntry::memdep_count == 0);
933025Ssaidi@eecs.umich.edu#endif
943143Shsul@eecs.umich.edu}
953143Shsul@eecs.umich.edu
963322Shsul@eecs.umich.edutemplate <class MemDepPred, class Impl>
973444Sktlim@umich.eduvoid
983322Shsul@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::init(DerivO3CPUParams *params, ThreadID tid)
992710SN/A{
1002710SN/A    DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid);
1012710SN/A
1022710SN/A    _name = csprintf("%s.memDep%d", params->name, tid);
1032710SN/A    id = tid;
1042710SN/A
1053322Shsul@eecs.umich.edu    depPred.init(params->store_set_clear_period, params->SSITSize,
1063304Sstever@eecs.umich.edu            params->LFSTSize);
1073322Shsul@eecs.umich.edu}
1083322Shsul@eecs.umich.edu
1093304Sstever@eecs.umich.edutemplate <class MemDepPred, class Impl>
1103481Shsul@eecs.umich.eduvoid
1113481Shsul@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::regStats()
1122566SN/A{
1133322Shsul@eecs.umich.edu    insertedLoads
1143322Shsul@eecs.umich.edu        .name(name() + ".insertedLoads")
1152995SN/A        .desc("Number of loads inserted to the mem dependence unit.");
1162995SN/A
1173304Sstever@eecs.umich.edu    insertedStores
1183304Sstever@eecs.umich.edu        .name(name() + ".insertedStores")
1193304Sstever@eecs.umich.edu        .desc("Number of stores inserted to the mem dependence unit.");
1202995SN/A
1212995SN/A    conflictingLoads
1222995SN/A        .name(name() + ".conflictingLoads")
1232917SN/A        .desc("Number of conflicting loads.");
1242995SN/A
1253304Sstever@eecs.umich.edu    conflictingStores
1262995SN/A        .name(name() + ".conflictingStores")
1273304Sstever@eecs.umich.edu        .desc("Number of conflicting stores.");
1283304Sstever@eecs.umich.edu}
1296135Sgblack@eecs.umich.edu
1306135Sgblack@eecs.umich.edutemplate <class MemDepPred, class Impl>
1316654Snate@binkert.orgbool
1323819Shsul@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::isDrained() const
1336654Snate@binkert.org{
1345222Sksewell@umich.edu    bool drained = instsToReplay.empty()
1356654Snate@binkert.org                 && memDepHash.empty()
1363819Shsul@eecs.umich.edu                 && instsToReplay.empty();
1376654Snate@binkert.org    for (int i = 0; i < Impl::MaxThreads; ++i)
1387925Sgblack@eecs.umich.edu        drained = drained && instList[i].empty();
1397925Sgblack@eecs.umich.edu
1407586SAli.Saidi@arm.com    return drained;
1418061SAli.Saidi@ARM.com}
1428061SAli.Saidi@ARM.com
1438061SAli.Saidi@ARM.comtemplate <class MemDepPred, class Impl>
1448354Sgedare@gwmail.gwu.eduvoid
1453819Shsul@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::drainSanityCheck() const
1466654Snate@binkert.org{
1473819Shsul@eecs.umich.edu    assert(instsToReplay.empty());
1483873Sbinkertn@umich.edu    assert(memDepHash.empty());
1493873Sbinkertn@umich.edu    for (int i = 0; i < Impl::MaxThreads; ++i)
1503873Sbinkertn@umich.edu        assert(instList[i].empty());
1513873Sbinkertn@umich.edu    assert(instsToReplay.empty());
1523873Sbinkertn@umich.edu    assert(memDepHash.empty());
1533873Sbinkertn@umich.edu}
1548659SAli.Saidi@ARM.com
1558659SAli.Saidi@ARM.comtemplate <class MemDepPred, class Impl>
1566995Sgblack@eecs.umich.eduvoid
1573668Srdreslin@umich.eduMemDepUnit<MemDepPred, Impl>::takeOverFrom()
1586995Sgblack@eecs.umich.edu{
1595142Ssaidi@eecs.umich.edu    // Be sure to reset all state.
1608713Sandreas.hansson@arm.com    loadBarrier = storeBarrier = false;
1618713Sandreas.hansson@arm.com    loadBarrierSN = storeBarrierSN = 0;
1628713Sandreas.hansson@arm.com    depPred.clear();
1638713Sandreas.hansson@arm.com}
1646636Ssteve.reinhardt@amd.com
1657586SAli.Saidi@arm.comtemplate <class MemDepPred, class Impl>
1665142Ssaidi@eecs.umich.eduvoid
1675142Ssaidi@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr)
1688713Sandreas.hansson@arm.com{
1698713Sandreas.hansson@arm.com    iqPtr = iq_ptr;
1708723Sandreas.hansson@arm.com}
1718713Sandreas.hansson@arm.com
1728713Sandreas.hansson@arm.comtemplate <class MemDepPred, class Impl>
1735142Ssaidi@eecs.umich.eduvoid
1743312Sstever@eecs.umich.eduMemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
1754968Sacolyte@umich.edu{
1764968Sacolyte@umich.edu    ThreadID tid = inst->threadNumber;
1774968Sacolyte@umich.edu
1786654Snate@binkert.org    MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(inst);
1795254Sksewell@umich.edu
1805222Sksewell@umich.edu    // Add the MemDepEntry to the hash.
1813005Sstever@eecs.umich.edu    memDepHash.insert(
1826654Snate@binkert.org        std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
1833819Shsul@eecs.umich.edu#ifdef DEBUG
1846654Snate@binkert.org    MemDepEntry::memdep_insert++;
1855222Sksewell@umich.edu#endif
1866654Snate@binkert.org
1873819Shsul@eecs.umich.edu    instList[tid].push_back(inst);
1886654Snate@binkert.org
1896135Sgblack@eecs.umich.edu    inst_entry->listIt = --(instList[tid].end());
1907586SAli.Saidi@arm.com
1918661SAli.Saidi@ARM.com    // Check any barriers and the dependence predictor for any
1928661SAli.Saidi@ARM.com    // producing memrefs/stores.
1933322Shsul@eecs.umich.edu    InstSeqNum producing_store;
1947876Sgblack@eecs.umich.edu    if (inst->isLoad() && loadBarrier) {
1954968Sacolyte@umich.edu        DPRINTF(MemDepUnit, "Load barrier [sn:%lli] in flight\n",
1964968Sacolyte@umich.edu                loadBarrierSN);
1974837Ssaidi@eecs.umich.edu        producing_store = loadBarrierSN;
1984837Ssaidi@eecs.umich.edu    } else if (inst->isStore() && storeBarrier) {
1994837Ssaidi@eecs.umich.edu        DPRINTF(MemDepUnit, "Store barrier [sn:%lli] in flight\n",
2008659SAli.Saidi@ARM.com                storeBarrierSN);
2018801Sgblack@eecs.umich.edu        producing_store = storeBarrierSN;
2023005Sstever@eecs.umich.edu    } else {
2038801Sgblack@eecs.umich.edu        producing_store = depPred.checkInst(inst->instAddr());
2043005Sstever@eecs.umich.edu    }
2053005Sstever@eecs.umich.edu
2063005Sstever@eecs.umich.edu    MemDepEntryPtr store_entry = NULL;
2072566SN/A
2087861Sgblack@eecs.umich.edu    // If there is a producing store, try to find the entry.
2097861Sgblack@eecs.umich.edu    if (producing_store != 0) {
2107861Sgblack@eecs.umich.edu        DPRINTF(MemDepUnit, "Searching for producer\n");
2118635Schris.emmons@arm.com        MemDepHashIt hash_it = memDepHash.find(producing_store);
2128635Schris.emmons@arm.com
2138635Schris.emmons@arm.com        if (hash_it != memDepHash.end()) {
2143481Shsul@eecs.umich.edu            store_entry = (*hash_it).second;
215            DPRINTF(MemDepUnit, "Proucer found\n");
216        }
217    }
218
219    // If no store entry, then instruction can issue as soon as the registers
220    // are ready.
221    if (!store_entry) {
222        DPRINTF(MemDepUnit, "No dependency for inst PC "
223                "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
224
225        inst_entry->memDepReady = true;
226
227        if (inst->readyToIssue()) {
228            inst_entry->regsReady = true;
229
230            moveToReady(inst_entry);
231        }
232    } else {
233        // Otherwise make the instruction dependent on the store/barrier.
234        DPRINTF(MemDepUnit, "Adding to dependency list; "
235                "inst PC %s is dependent on [sn:%lli].\n",
236                inst->pcState(), producing_store);
237
238        if (inst->readyToIssue()) {
239            inst_entry->regsReady = true;
240        }
241
242        // Clear the bit saying this instruction can issue.
243        inst->clearCanIssue();
244
245        // Add this instruction to the list of dependents.
246        store_entry->dependInsts.push_back(inst_entry);
247
248        if (inst->isLoad()) {
249            ++conflictingLoads;
250        } else {
251            ++conflictingStores;
252        }
253    }
254
255    if (inst->isStore()) {
256        DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
257                inst->pcState(), inst->seqNum);
258
259        depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
260
261        ++insertedStores;
262    } else if (inst->isLoad()) {
263        ++insertedLoads;
264    } else {
265        panic("Unknown type! (most likely a barrier).");
266    }
267}
268
269template <class MemDepPred, class Impl>
270void
271MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
272{
273    ThreadID tid = inst->threadNumber;
274
275    MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(inst);
276
277    // Insert the MemDepEntry into the hash.
278    memDepHash.insert(
279        std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
280#ifdef DEBUG
281    MemDepEntry::memdep_insert++;
282#endif
283
284    // Add the instruction to the list.
285    instList[tid].push_back(inst);
286
287    inst_entry->listIt = --(instList[tid].end());
288
289    // Might want to turn this part into an inline function or something.
290    // It's shared between both insert functions.
291    if (inst->isStore()) {
292        DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
293                inst->pcState(), inst->seqNum);
294
295        depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
296
297        ++insertedStores;
298    } else if (inst->isLoad()) {
299        ++insertedLoads;
300    } else {
301        panic("Unknown type! (most likely a barrier).");
302    }
303}
304
305template <class MemDepPred, class Impl>
306void
307MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
308{
309    InstSeqNum barr_sn = barr_inst->seqNum;
310    // Memory barriers block loads and stores, write barriers only stores.
311    if (barr_inst->isMemBarrier()) {
312        loadBarrier = true;
313        loadBarrierSN = barr_sn;
314        storeBarrier = true;
315        storeBarrierSN = barr_sn;
316        DPRINTF(MemDepUnit, "Inserted a memory barrier %s SN:%lli\n",
317                barr_inst->pcState(),barr_sn);
318    } else if (barr_inst->isWriteBarrier()) {
319        storeBarrier = true;
320        storeBarrierSN = barr_sn;
321        DPRINTF(MemDepUnit, "Inserted a write barrier\n");
322    }
323
324    ThreadID tid = barr_inst->threadNumber;
325
326    MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
327
328    // Add the MemDepEntry to the hash.
329    memDepHash.insert(
330        std::pair<InstSeqNum, MemDepEntryPtr>(barr_sn, inst_entry));
331#ifdef DEBUG
332    MemDepEntry::memdep_insert++;
333#endif
334
335    // Add the instruction to the instruction list.
336    instList[tid].push_back(barr_inst);
337
338    inst_entry->listIt = --(instList[tid].end());
339}
340
341template <class MemDepPred, class Impl>
342void
343MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
344{
345    DPRINTF(MemDepUnit, "Marking registers as ready for "
346            "instruction PC %s [sn:%lli].\n",
347            inst->pcState(), inst->seqNum);
348
349    MemDepEntryPtr inst_entry = findInHash(inst);
350
351    inst_entry->regsReady = true;
352
353    if (inst_entry->memDepReady) {
354        DPRINTF(MemDepUnit, "Instruction has its memory "
355                "dependencies resolved, adding it to the ready list.\n");
356
357        moveToReady(inst_entry);
358    } else {
359        DPRINTF(MemDepUnit, "Instruction still waiting on "
360                "memory dependency.\n");
361    }
362}
363
364template <class MemDepPred, class Impl>
365void
366MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
367{
368    DPRINTF(MemDepUnit, "Marking non speculative "
369            "instruction PC %s as ready [sn:%lli].\n",
370            inst->pcState(), inst->seqNum);
371
372    MemDepEntryPtr inst_entry = findInHash(inst);
373
374    moveToReady(inst_entry);
375}
376
377template <class MemDepPred, class Impl>
378void
379MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
380{
381    instsToReplay.push_back(inst);
382}
383
384template <class MemDepPred, class Impl>
385void
386MemDepUnit<MemDepPred, Impl>::replay()
387{
388    DynInstPtr temp_inst;
389
390    // For now this replay function replays all waiting memory ops.
391    while (!instsToReplay.empty()) {
392        temp_inst = instsToReplay.front();
393
394        MemDepEntryPtr inst_entry = findInHash(temp_inst);
395
396        DPRINTF(MemDepUnit, "Replaying mem instruction PC %s [sn:%lli].\n",
397                temp_inst->pcState(), temp_inst->seqNum);
398
399        moveToReady(inst_entry);
400
401        instsToReplay.pop_front();
402    }
403}
404
405template <class MemDepPred, class Impl>
406void
407MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
408{
409    DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n",
410            inst->pcState(), inst->seqNum);
411
412    ThreadID tid = inst->threadNumber;
413
414    // Remove the instruction from the hash and the list.
415    MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
416
417    assert(hash_it != memDepHash.end());
418
419    instList[tid].erase((*hash_it).second->listIt);
420
421    (*hash_it).second = NULL;
422
423    memDepHash.erase(hash_it);
424#ifdef DEBUG
425    MemDepEntry::memdep_erase++;
426#endif
427}
428
429template <class MemDepPred, class Impl>
430void
431MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
432{
433    wakeDependents(inst);
434    completed(inst);
435
436    InstSeqNum barr_sn = inst->seqNum;
437    DPRINTF(MemDepUnit, "barrier completed: %s SN:%lli\n", inst->pcState(),
438            inst->seqNum);
439    if (inst->isMemBarrier()) {
440        if (loadBarrierSN == barr_sn)
441            loadBarrier = false;
442        if (storeBarrierSN == barr_sn)
443            storeBarrier = false;
444    } else if (inst->isWriteBarrier()) {
445        if (storeBarrierSN == barr_sn)
446            storeBarrier = false;
447    }
448}
449
450template <class MemDepPred, class Impl>
451void
452MemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
453{
454    // Only stores and barriers have dependents.
455    if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
456        return;
457    }
458
459    MemDepEntryPtr inst_entry = findInHash(inst);
460
461    for (int i = 0; i < inst_entry->dependInsts.size(); ++i ) {
462        MemDepEntryPtr woken_inst = inst_entry->dependInsts[i];
463
464        if (!woken_inst->inst) {
465            // Potentially removed mem dep entries could be on this list
466            continue;
467        }
468
469        DPRINTF(MemDepUnit, "Waking up a dependent inst, "
470                "[sn:%lli].\n",
471                woken_inst->inst->seqNum);
472
473        if (woken_inst->regsReady && !woken_inst->squashed) {
474            moveToReady(woken_inst);
475        } else {
476            woken_inst->memDepReady = true;
477        }
478    }
479
480    inst_entry->dependInsts.clear();
481}
482
483template <class MemDepPred, class Impl>
484void
485MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
486                                     ThreadID tid)
487{
488    if (!instsToReplay.empty()) {
489        ListIt replay_it = instsToReplay.begin();
490        while (replay_it != instsToReplay.end()) {
491            if ((*replay_it)->threadNumber == tid &&
492                (*replay_it)->seqNum > squashed_num) {
493                instsToReplay.erase(replay_it++);
494            } else {
495                ++replay_it;
496            }
497        }
498    }
499
500    ListIt squash_it = instList[tid].end();
501    --squash_it;
502
503    MemDepHashIt hash_it;
504
505    while (!instList[tid].empty() &&
506           (*squash_it)->seqNum > squashed_num) {
507
508        DPRINTF(MemDepUnit, "Squashing inst [sn:%lli]\n",
509                (*squash_it)->seqNum);
510
511        if ((*squash_it)->seqNum == loadBarrierSN)
512              loadBarrier = false;
513
514        if ((*squash_it)->seqNum == storeBarrierSN)
515              storeBarrier = false;
516
517        hash_it = memDepHash.find((*squash_it)->seqNum);
518
519        assert(hash_it != memDepHash.end());
520
521        (*hash_it).second->squashed = true;
522
523        (*hash_it).second = NULL;
524
525        memDepHash.erase(hash_it);
526#ifdef DEBUG
527        MemDepEntry::memdep_erase++;
528#endif
529
530        instList[tid].erase(squash_it--);
531    }
532
533    // Tell the dependency predictor to squash as well.
534    depPred.squash(squashed_num, tid);
535}
536
537template <class MemDepPred, class Impl>
538void
539MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
540                                        DynInstPtr &violating_load)
541{
542    DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
543            " load: %#x, store: %#x\n", violating_load->instAddr(),
544            store_inst->instAddr());
545    // Tell the memory dependence unit of the violation.
546    depPred.violation(store_inst->instAddr(), violating_load->instAddr());
547}
548
549template <class MemDepPred, class Impl>
550void
551MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
552{
553    DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
554            inst->instAddr(), inst->seqNum);
555
556    depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
557}
558
559template <class MemDepPred, class Impl>
560inline typename MemDepUnit<MemDepPred,Impl>::MemDepEntryPtr &
561MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstPtr &inst)
562{
563    MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
564
565    assert(hash_it != memDepHash.end());
566
567    return (*hash_it).second;
568}
569
570template <class MemDepPred, class Impl>
571inline void
572MemDepUnit<MemDepPred, Impl>::moveToReady(MemDepEntryPtr &woken_inst_entry)
573{
574    DPRINTF(MemDepUnit, "Adding instruction [sn:%lli] "
575            "to the ready list.\n", woken_inst_entry->inst->seqNum);
576
577    assert(!woken_inst_entry->squashed);
578
579    iqPtr->addReadyMemInst(woken_inst_entry->inst);
580}
581
582
583template <class MemDepPred, class Impl>
584void
585MemDepUnit<MemDepPred, Impl>::dumpLists()
586{
587    for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
588        cprintf("Instruction list %i size: %i\n",
589                tid, instList[tid].size());
590
591        ListIt inst_list_it = instList[tid].begin();
592        int num = 0;
593
594        while (inst_list_it != instList[tid].end()) {
595            cprintf("Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
596                    "Squashed:%i\n\n",
597                    num, (*inst_list_it)->pcState(),
598                    (*inst_list_it)->seqNum,
599                    (*inst_list_it)->threadNumber,
600                    (*inst_list_it)->isIssued(),
601                    (*inst_list_it)->isSquashed());
602            inst_list_it++;
603            ++num;
604        }
605    }
606
607    cprintf("Memory dependence hash size: %i\n", memDepHash.size());
608
609#ifdef DEBUG
610    cprintf("Memory dependence entries: %i\n", MemDepEntry::memdep_count);
611#endif
612}
613
614#endif//__CPU_O3_MEM_DEP_UNIT_IMPL_HH__
615