mem_dep_unit_impl.hh revision 1062
1837SN/A
21762SN/A#include <map>
3837SN/A
4837SN/A#include "cpu/beta_cpu/mem_dep_unit.hh"
5837SN/A
6837SN/Atemplate <class MemDepPred, class Impl>
7837SN/AMemDepUnit<MemDepPred, Impl>::MemDepUnit(Params &params)
8837SN/A    : depPred(params.SSITSize, params.LFSTSize)
9837SN/A{
10837SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Creating MemDepUnit object.\n");
11837SN/A}
12837SN/A
13837SN/Atemplate <class MemDepPred, class Impl>
14837SN/Avoid
15837SN/AMemDepUnit<MemDepPred, Impl>::regStats()
16837SN/A{
17837SN/A    insertedLoads
18837SN/A        .name(name() + ".memDep.insertedLoads")
19837SN/A        .desc("Number of loads inserted to the mem dependence unit.");
20837SN/A
21837SN/A    insertedStores
22837SN/A        .name(name() + ".memDep.insertedStores")
23837SN/A        .desc("Number of stores inserted to the mem dependence unit.");
24837SN/A
25837SN/A    conflictingLoads
26837SN/A        .name(name() + ".memDep.conflictingLoads")
272665SN/A        .desc("Number of conflicting loads.");
282760SN/A
292760SN/A    conflictingStores
30837SN/A        .name(name() + ".memDep.conflictingStores")
31837SN/A        .desc("Number of conflicting stores.");
321730SN/A}
33837SN/A
34837SN/Atemplate <class MemDepPred, class Impl>
35837SN/Avoid
3611263Sandreas.sandberg@arm.comMemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
3711263Sandreas.sandberg@arm.com{
3811263Sandreas.sandberg@arm.com    InstSeqNum inst_seq_num = inst->seqNum;
39837SN/A
4010469SN/A    Dependency unresolved_dependencies(inst_seq_num);
41837SN/A
42837SN/A    InstSeqNum producing_store = depPred.checkInst(inst->readPC());
435882SN/A
44837SN/A    if (producing_store == 0 ||
456216SN/A        storeDependents.find(producing_store) == storeDependents.end()) {
466658SN/A
478232SN/A        DPRINTF(MemDepUnit, "MemDepUnit: No dependency for inst PC "
4811263Sandreas.sandberg@arm.com                "%#x.\n", inst->readPC());
492566SN/A
503348SN/A        unresolved_dependencies.storeDep = storeDependents.end();
514762SN/A
522566SN/A        if (inst->readyToIssue()) {
53854SN/A            readyInsts.insert(inst_seq_num);
548737SN/A        } else {
558737SN/A            unresolved_dependencies.memDepReady = true;
5610469SN/A
578737SN/A            waitingInsts.insert(unresolved_dependencies);
588737SN/A        }
598737SN/A    } else {
608737SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Adding to dependency list; "
61854SN/A                "inst PC %#x is dependent on seq num %i.\n",
62854SN/A                inst->readPC(), producing_store);
63854SN/A
64854SN/A        if (inst->readyToIssue()) {
65854SN/A            unresolved_dependencies.regsReady = true;
66854SN/A        }
67854SN/A
68854SN/A        // Find the store that this instruction is dependent on.
69854SN/A        sd_it_t store_loc = storeDependents.find(producing_store);
70854SN/A
71854SN/A        assert(store_loc != storeDependents.end());
72854SN/A
73854SN/A        // Record the location of the store that this instruction is
74854SN/A        // dependent on.
75854SN/A        unresolved_dependencies.storeDep = store_loc;
76854SN/A
77854SN/A        // If it's not already ready, then add it to the renamed
78854SN/A        // list and the dependencies.
79854SN/A        dep_it_t inst_loc =
80854SN/A            (waitingInsts.insert(unresolved_dependencies)).first;
81854SN/A
82854SN/A        // Add this instruction to the list of dependents.
83854SN/A        (*store_loc).second.push_back(inst_loc);
84854SN/A
85854SN/A        assert(!(*store_loc).second.empty());
86854SN/A
87854SN/A        if (inst->isLoad()) {
88854SN/A            ++conflictingLoads;
89854SN/A        } else {
90854SN/A            ++conflictingStores;
91837SN/A        }
921114SN/A    }
932107SN/A
94927SN/A    if (inst->isStore()) {
95837SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
96837SN/A                inst->readPC());
97879SN/A
98837SN/A        depPred.insertStore(inst->readPC(), inst_seq_num);
991149SN/A
1009339SN/A        // Make sure this store isn't already in this list.
1011149SN/A        assert(storeDependents.find(inst_seq_num) == storeDependents.end());
102915SN/A
1034093SN/A        // Put a dependency entry in at the store's sequence number.
1044093SN/A        // Uh, not sure how this works...I want to create an entry but
105854SN/A        // I don't have anything to put into the value yet.
1064093SN/A        storeDependents[inst_seq_num];
107854SN/A
1084093SN/A        assert(storeDependents.size() != 0);
1094093SN/A
1104093SN/A        ++insertedStores;
1114093SN/A
1124093SN/A    } else if (inst->isLoad()) {
1134093SN/A        ++insertedLoads;
11412087Sspwilson2@wisc.edu    } else {
11512087Sspwilson2@wisc.edu        panic("MemDepUnit: Unknown type! (most likely a barrier).");
11612087Sspwilson2@wisc.edu    }
11712087Sspwilson2@wisc.edu
1181149SN/A    memInsts[inst_seq_num] = inst;
1191149SN/A}
12012087Sspwilson2@wisc.edu
12112087Sspwilson2@wisc.edutemplate <class MemDepPred, class Impl>
12212087Sspwilson2@wisc.eduvoid
12312087Sspwilson2@wisc.eduMemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
12412087Sspwilson2@wisc.edu{
12512087Sspwilson2@wisc.edu    InstSeqNum inst_seq_num = inst->seqNum;
1264093SN/A
1271843SN/A    Dependency non_spec_inst(inst_seq_num);
1284093SN/A
129995SN/A    non_spec_inst.storeDep = storeDependents.end();
130837SN/A
131854SN/A    waitingInsts.insert(non_spec_inst);
132854SN/A
1334981SN/A    // Might want to turn this part into an inline function or something.
1344981SN/A    // It's shared between both insert functions.
135837SN/A    if (inst->isStore()) {
1364762SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
1371909SN/A                inst->readPC());
1381909SN/A
1391909SN/A        depPred.insertStore(inst->readPC(), inst_seq_num);
1401909SN/A
1411909SN/A        // Make sure this store isn't already in this list.
142837SN/A        assert(storeDependents.find(inst_seq_num) == storeDependents.end());
143837SN/A
144879SN/A        // Put a dependency entry in at the store's sequence number.
1459086SN/A        // Uh, not sure how this works...I want to create an entry but
1469086SN/A        // I don't have anything to put into the value yet.
1479086SN/A        storeDependents[inst_seq_num];
148837SN/A
149855SN/A        assert(storeDependents.size() != 0);
150855SN/A
151855SN/A        ++insertedStores;
1522846SN/A
1533349SN/A    } else if (inst->isLoad()) {
154837SN/A        ++insertedLoads;
1552846SN/A    } else {
156837SN/A        panic("MemDepUnit: Unknown type! (most likely a barrier).");
1579807SN/A    }
158837SN/A
159897SN/A    memInsts[inst_seq_num] = inst;
160897SN/A}
161897SN/A
1621027SN/Atemplate <class MemDepPred, class Impl>
1631027SN/Atypename Impl::DynInstPtr &
1641027SN/AMemDepUnit<MemDepPred, Impl>::top()
165917SN/A{
166917SN/A    topInst = memInsts.find( (*readyInsts.begin()) );
167927SN/A
168917SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Top instruction is PC %#x.\n",
169927SN/A            (*topInst).second->readPC());
170897SN/A
171897SN/A    return (*topInst).second;
1724875SN/A}
1732846SN/A
174837SN/Atemplate <class MemDepPred, class Impl>
175837SN/Avoid
1764981SN/AMemDepUnit<MemDepPred, Impl>::pop()
1774981SN/A{
1784981SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Removing instruction PC %#x.\n",
1794981SN/A            (*topInst).second->readPC());
1804981SN/A
1814981SN/A    wakeDependents((*topInst).second);
1824981SN/A
1834981SN/A    issue((*topInst).second);
1844981SN/A
1854981SN/A    memInsts.erase(topInst);
1864981SN/A
187855SN/A    topInst = memInsts.end();
188855SN/A}
189855SN/A
190855SN/Atemplate <class MemDepPred, class Impl>
1912566SN/Avoid
1923349SN/AMemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
193837SN/A{
194927SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Marking registers as ready for "
195917SN/A            "instruction PC %#x.\n",
196855SN/A            inst->readPC());
1972641SN/A
1982566SN/A    InstSeqNum inst_seq_num = inst->seqNum;
1992641SN/A
200837SN/A    Dependency inst_to_find(inst_seq_num);
201855SN/A
2021027SN/A    dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
2031027SN/A
204854SN/A    assert(waiting_inst != waitingInsts.end());
205837SN/A
206854SN/A    if ((*waiting_inst).memDepReady) {
2072846SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Instruction has its memory "
208854SN/A                "dependencies resolved, adding it to the ready list.\n");
209854SN/A
210854SN/A        moveToReady(waiting_inst);
211855SN/A    } else {
2122630SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Instruction still waiting on "
2134870SN/A                "memory dependency.\n");
2142566SN/A
215854SN/A        (*waiting_inst).regsReady = true;
216854SN/A    }
217837SN/A}
2182641SN/A
2192630SN/Atemplate <class MemDepPred, class Impl>
2202566SN/Avoid
2212566SN/AMemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
2222566SN/A{
2232566SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Marking non speculative "
2242566SN/A            "instruction PC %#x as ready.\n",
2252566SN/A            inst->readPC());
2262566SN/A
2272566SN/A    InstSeqNum inst_seq_num = inst->seqNum;
2282566SN/A
2292566SN/A    Dependency inst_to_find(inst_seq_num);
2302566SN/A
2312566SN/A    dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
2322566SN/A
2332566SN/A    assert(waiting_inst != waitingInsts.end());
2342566SN/A
2352566SN/A    moveToReady(waiting_inst);
2362566SN/A}
2372566SN/A
2382566SN/Atemplate <class MemDepPred, class Impl>
2392566SN/Avoid
2402566SN/AMemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
2412566SN/A{
2422566SN/A    assert(readyInsts.find(inst->seqNum) != readyInsts.end());
2432566SN/A
2442566SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Issuing instruction PC %#x.\n",
2452566SN/A            inst->readPC());
2462566SN/A
2472566SN/A    // Remove the instruction from the ready list.
2482566SN/A    readyInsts.erase(inst->seqNum);
2492566SN/A
2502566SN/A    depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
2512566SN/A}
2522566SN/A
2532566SN/Atemplate <class MemDepPred, class Impl>
2542566SN/Avoid
2552566SN/AMemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
2562566SN/A{
2572566SN/A    // Only stores have dependents.
2582566SN/A    if (!inst->isStore()) {
2592566SN/A        return;
2602566SN/A    }
2612566SN/A
2622566SN/A    // Wake any dependencies.
2632566SN/A    sd_it_t sd_it = storeDependents.find(inst->seqNum);
2642566SN/A
2652566SN/A    // If there's no entry, then return.  Really there should only be
2662566SN/A    // no entry if the instruction is a load.
2672566SN/A    if (sd_it == storeDependents.end()) {
2682566SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Instruction PC %#x, sequence "
2692566SN/A                "number %i has no dependents.\n",
2702566SN/A                inst->readPC(), inst->seqNum);
2712566SN/A
2722566SN/A        return;
2732566SN/A    }
2742566SN/A
2752566SN/A    for (int i = 0; i < (*sd_it).second.size(); ++i ) {
2762566SN/A        dep_it_t woken_inst = (*sd_it).second[i];
2772566SN/A
2782566SN/A        DPRINTF(MemDepUnit, "MemDepUnit: Waking up a dependent inst, "
2792566SN/A                "sequence number %i.\n",
2802566SN/A                (*woken_inst).seqNum);
2812566SN/A#if 0
2822566SN/A        // Should we have reached instructions that are actually squashed,
2832566SN/A        // there will be no more useful instructions in this dependency
2842566SN/A        // list.  Break out early.
2852566SN/A        if (waitingInsts.find(woken_inst) == waitingInsts.end()) {
2862566SN/A            DPRINTF(MemDepUnit, "MemDepUnit: Dependents on inst PC %#x "
2872566SN/A                    "are squashed, starting at SN %i.  Breaking early.\n",
2882566SN/A                    inst->readPC(), woken_inst);
2892566SN/A            break;
2902566SN/A        }
2912566SN/A#endif
2922566SN/A
2932566SN/A        if ((*woken_inst).regsReady) {
2942566SN/A            moveToReady(woken_inst);
2952566SN/A        } else {
2962566SN/A            (*woken_inst).memDepReady = true;
2972566SN/A        }
2982566SN/A    }
2992566SN/A
3002566SN/A    storeDependents.erase(sd_it);
3012566SN/A}
3022566SN/A
3032566SN/Atemplate <class MemDepPred, class Impl>
3042566SN/Avoid
3052566SN/AMemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num)
3062566SN/A{
3072566SN/A
3082566SN/A    if (!waitingInsts.empty()) {
3092566SN/A        dep_it_t waiting_it = waitingInsts.end();
3102566SN/A
3112566SN/A        --waiting_it;
3122566SN/A
3132566SN/A        // Remove entries from the renamed list as long as we haven't reached
3142566SN/A        // the end and the entries continue to be younger than the squashed.
315837SN/A        while (!waitingInsts.empty() &&
3162566SN/A               (*waiting_it).seqNum > squashed_num)
3172566SN/A        {
3182566SN/A            if (!(*waiting_it).memDepReady &&
319837SN/A                (*waiting_it).storeDep != storeDependents.end()) {
3202566SN/A                sd_it_t sd_it = (*waiting_it).storeDep;
3212566SN/A
3222566SN/A                // Make sure the iterator that the store has pointing
323837SN/A                // back is actually to this instruction.
3242566SN/A                assert((*sd_it).second.back() == waiting_it);
3252566SN/A
3262566SN/A                // Now remove this from the store's list of dependent
3272566SN/A                // instructions.
3282566SN/A                (*sd_it).second.pop_back();
3292566SN/A            }
3302566SN/A
3312566SN/A            waitingInsts.erase(waiting_it--);
3322566SN/A        }
3332566SN/A    }
3342566SN/A
335837SN/A    if (!readyInsts.empty()) {
336837SN/A        sn_it_t ready_it = readyInsts.end();
3372566SN/A
3382566SN/A        --ready_it;
3392566SN/A
340837SN/A        // Same for the ready list.
3412566SN/A        while (!readyInsts.empty() &&
3422566SN/A               (*ready_it) > squashed_num)
3432566SN/A        {
3442566SN/A            readyInsts.erase(ready_it--);
3452566SN/A        }
3462566SN/A    }
3472566SN/A
3482566SN/A    if (!storeDependents.empty()) {
3492566SN/A        sd_it_t dep_it = storeDependents.end();
3502566SN/A
3512566SN/A        --dep_it;
3522566SN/A
3532566SN/A        // Same for the dependencies list.
3542566SN/A        while (!storeDependents.empty() &&
3552566SN/A               (*dep_it).first > squashed_num)
3562566SN/A        {
3572566SN/A            // This store's list of dependent instructions should be empty.
3582566SN/A            assert((*dep_it).second.empty());
3592566SN/A
3602566SN/A            storeDependents.erase(dep_it--);
3612566SN/A        }
3622566SN/A    }
3632566SN/A
3642566SN/A    // Tell the dependency predictor to squash as well.
3652566SN/A    depPred.squash(squashed_num);
3662566SN/A}
3672566SN/A
3682566SN/Atemplate <class MemDepPred, class Impl>
3692566SN/Avoid
3702566SN/AMemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
3712566SN/A                                        DynInstPtr &violating_load)
3722566SN/A{
3732566SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Passing violating PCs to store sets,"
3742566SN/A            " load: %#x, store: %#x\n", violating_load->readPC(),
3752566SN/A            store_inst->readPC());
3762566SN/A    // Tell the memory dependence unit of the violation.
3772566SN/A    depPred.violation(violating_load->readPC(), store_inst->readPC());
3782566SN/A}
3792566SN/A
3802566SN/Atemplate <class MemDepPred, class Impl>
3812566SN/Ainline void
3822566SN/AMemDepUnit<MemDepPred, Impl>::moveToReady(dep_it_t &woken_inst)
3832566SN/A{
3842566SN/A    DPRINTF(MemDepUnit, "MemDepUnit: Adding instruction sequence number %i "
3852566SN/A            "to the ready list.\n", (*woken_inst).seqNum);
3862566SN/A
3872566SN/A    // Add it to the ready list.
3882566SN/A    readyInsts.insert((*woken_inst).seqNum);
3892566SN/A
3902566SN/A    // Remove it from the waiting instructions.
3912566SN/A    waitingInsts.erase(woken_inst);
3922566SN/A}
3932566SN/A