mem_dep_unit_impl.hh revision 1062
1
2#include <map>
3
4#include "cpu/beta_cpu/mem_dep_unit.hh"
5
6template <class MemDepPred, class Impl>
7MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params &params)
8    : depPred(params.SSITSize, params.LFSTSize)
9{
10    DPRINTF(MemDepUnit, "MemDepUnit: Creating MemDepUnit object.\n");
11}
12
13template <class MemDepPred, class Impl>
14void
15MemDepUnit<MemDepPred, Impl>::regStats()
16{
17    insertedLoads
18        .name(name() + ".memDep.insertedLoads")
19        .desc("Number of loads inserted to the mem dependence unit.");
20
21    insertedStores
22        .name(name() + ".memDep.insertedStores")
23        .desc("Number of stores inserted to the mem dependence unit.");
24
25    conflictingLoads
26        .name(name() + ".memDep.conflictingLoads")
27        .desc("Number of conflicting loads.");
28
29    conflictingStores
30        .name(name() + ".memDep.conflictingStores")
31        .desc("Number of conflicting stores.");
32}
33
34template <class MemDepPred, class Impl>
35void
36MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
37{
38    InstSeqNum inst_seq_num = inst->seqNum;
39
40    Dependency unresolved_dependencies(inst_seq_num);
41
42    InstSeqNum producing_store = depPred.checkInst(inst->readPC());
43
44    if (producing_store == 0 ||
45        storeDependents.find(producing_store) == storeDependents.end()) {
46
47        DPRINTF(MemDepUnit, "MemDepUnit: No dependency for inst PC "
48                "%#x.\n", inst->readPC());
49
50        unresolved_dependencies.storeDep = storeDependents.end();
51
52        if (inst->readyToIssue()) {
53            readyInsts.insert(inst_seq_num);
54        } else {
55            unresolved_dependencies.memDepReady = true;
56
57            waitingInsts.insert(unresolved_dependencies);
58        }
59    } else {
60        DPRINTF(MemDepUnit, "MemDepUnit: Adding to dependency list; "
61                "inst PC %#x is dependent on seq num %i.\n",
62                inst->readPC(), producing_store);
63
64        if (inst->readyToIssue()) {
65            unresolved_dependencies.regsReady = true;
66        }
67
68        // Find the store that this instruction is dependent on.
69        sd_it_t store_loc = storeDependents.find(producing_store);
70
71        assert(store_loc != storeDependents.end());
72
73        // Record the location of the store that this instruction is
74        // dependent on.
75        unresolved_dependencies.storeDep = store_loc;
76
77        // If it's not already ready, then add it to the renamed
78        // list and the dependencies.
79        dep_it_t inst_loc =
80            (waitingInsts.insert(unresolved_dependencies)).first;
81
82        // Add this instruction to the list of dependents.
83        (*store_loc).second.push_back(inst_loc);
84
85        assert(!(*store_loc).second.empty());
86
87        if (inst->isLoad()) {
88            ++conflictingLoads;
89        } else {
90            ++conflictingStores;
91        }
92    }
93
94    if (inst->isStore()) {
95        DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
96                inst->readPC());
97
98        depPred.insertStore(inst->readPC(), inst_seq_num);
99
100        // Make sure this store isn't already in this list.
101        assert(storeDependents.find(inst_seq_num) == storeDependents.end());
102
103        // Put a dependency entry in at the store's sequence number.
104        // Uh, not sure how this works...I want to create an entry but
105        // I don't have anything to put into the value yet.
106        storeDependents[inst_seq_num];
107
108        assert(storeDependents.size() != 0);
109
110        ++insertedStores;
111
112    } else if (inst->isLoad()) {
113        ++insertedLoads;
114    } else {
115        panic("MemDepUnit: Unknown type! (most likely a barrier).");
116    }
117
118    memInsts[inst_seq_num] = inst;
119}
120
121template <class MemDepPred, class Impl>
122void
123MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
124{
125    InstSeqNum inst_seq_num = inst->seqNum;
126
127    Dependency non_spec_inst(inst_seq_num);
128
129    non_spec_inst.storeDep = storeDependents.end();
130
131    waitingInsts.insert(non_spec_inst);
132
133    // Might want to turn this part into an inline function or something.
134    // It's shared between both insert functions.
135    if (inst->isStore()) {
136        DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
137                inst->readPC());
138
139        depPred.insertStore(inst->readPC(), inst_seq_num);
140
141        // Make sure this store isn't already in this list.
142        assert(storeDependents.find(inst_seq_num) == storeDependents.end());
143
144        // Put a dependency entry in at the store's sequence number.
145        // Uh, not sure how this works...I want to create an entry but
146        // I don't have anything to put into the value yet.
147        storeDependents[inst_seq_num];
148
149        assert(storeDependents.size() != 0);
150
151        ++insertedStores;
152
153    } else if (inst->isLoad()) {
154        ++insertedLoads;
155    } else {
156        panic("MemDepUnit: Unknown type! (most likely a barrier).");
157    }
158
159    memInsts[inst_seq_num] = inst;
160}
161
162template <class MemDepPred, class Impl>
163typename Impl::DynInstPtr &
164MemDepUnit<MemDepPred, Impl>::top()
165{
166    topInst = memInsts.find( (*readyInsts.begin()) );
167
168    DPRINTF(MemDepUnit, "MemDepUnit: Top instruction is PC %#x.\n",
169            (*topInst).second->readPC());
170
171    return (*topInst).second;
172}
173
174template <class MemDepPred, class Impl>
175void
176MemDepUnit<MemDepPred, Impl>::pop()
177{
178    DPRINTF(MemDepUnit, "MemDepUnit: Removing instruction PC %#x.\n",
179            (*topInst).second->readPC());
180
181    wakeDependents((*topInst).second);
182
183    issue((*topInst).second);
184
185    memInsts.erase(topInst);
186
187    topInst = memInsts.end();
188}
189
190template <class MemDepPred, class Impl>
191void
192MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
193{
194    DPRINTF(MemDepUnit, "MemDepUnit: Marking registers as ready for "
195            "instruction PC %#x.\n",
196            inst->readPC());
197
198    InstSeqNum inst_seq_num = inst->seqNum;
199
200    Dependency inst_to_find(inst_seq_num);
201
202    dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
203
204    assert(waiting_inst != waitingInsts.end());
205
206    if ((*waiting_inst).memDepReady) {
207        DPRINTF(MemDepUnit, "MemDepUnit: Instruction has its memory "
208                "dependencies resolved, adding it to the ready list.\n");
209
210        moveToReady(waiting_inst);
211    } else {
212        DPRINTF(MemDepUnit, "MemDepUnit: Instruction still waiting on "
213                "memory dependency.\n");
214
215        (*waiting_inst).regsReady = true;
216    }
217}
218
219template <class MemDepPred, class Impl>
220void
221MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
222{
223    DPRINTF(MemDepUnit, "MemDepUnit: Marking non speculative "
224            "instruction PC %#x as ready.\n",
225            inst->readPC());
226
227    InstSeqNum inst_seq_num = inst->seqNum;
228
229    Dependency inst_to_find(inst_seq_num);
230
231    dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
232
233    assert(waiting_inst != waitingInsts.end());
234
235    moveToReady(waiting_inst);
236}
237
238template <class MemDepPred, class Impl>
239void
240MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
241{
242    assert(readyInsts.find(inst->seqNum) != readyInsts.end());
243
244    DPRINTF(MemDepUnit, "MemDepUnit: Issuing instruction PC %#x.\n",
245            inst->readPC());
246
247    // Remove the instruction from the ready list.
248    readyInsts.erase(inst->seqNum);
249
250    depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
251}
252
253template <class MemDepPred, class Impl>
254void
255MemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
256{
257    // Only stores have dependents.
258    if (!inst->isStore()) {
259        return;
260    }
261
262    // Wake any dependencies.
263    sd_it_t sd_it = storeDependents.find(inst->seqNum);
264
265    // If there's no entry, then return.  Really there should only be
266    // no entry if the instruction is a load.
267    if (sd_it == storeDependents.end()) {
268        DPRINTF(MemDepUnit, "MemDepUnit: Instruction PC %#x, sequence "
269                "number %i has no dependents.\n",
270                inst->readPC(), inst->seqNum);
271
272        return;
273    }
274
275    for (int i = 0; i < (*sd_it).second.size(); ++i ) {
276        dep_it_t woken_inst = (*sd_it).second[i];
277
278        DPRINTF(MemDepUnit, "MemDepUnit: Waking up a dependent inst, "
279                "sequence number %i.\n",
280                (*woken_inst).seqNum);
281#if 0
282        // Should we have reached instructions that are actually squashed,
283        // there will be no more useful instructions in this dependency
284        // list.  Break out early.
285        if (waitingInsts.find(woken_inst) == waitingInsts.end()) {
286            DPRINTF(MemDepUnit, "MemDepUnit: Dependents on inst PC %#x "
287                    "are squashed, starting at SN %i.  Breaking early.\n",
288                    inst->readPC(), woken_inst);
289            break;
290        }
291#endif
292
293        if ((*woken_inst).regsReady) {
294            moveToReady(woken_inst);
295        } else {
296            (*woken_inst).memDepReady = true;
297        }
298    }
299
300    storeDependents.erase(sd_it);
301}
302
303template <class MemDepPred, class Impl>
304void
305MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num)
306{
307
308    if (!waitingInsts.empty()) {
309        dep_it_t waiting_it = waitingInsts.end();
310
311        --waiting_it;
312
313        // Remove entries from the renamed list as long as we haven't reached
314        // the end and the entries continue to be younger than the squashed.
315        while (!waitingInsts.empty() &&
316               (*waiting_it).seqNum > squashed_num)
317        {
318            if (!(*waiting_it).memDepReady &&
319                (*waiting_it).storeDep != storeDependents.end()) {
320                sd_it_t sd_it = (*waiting_it).storeDep;
321
322                // Make sure the iterator that the store has pointing
323                // back is actually to this instruction.
324                assert((*sd_it).second.back() == waiting_it);
325
326                // Now remove this from the store's list of dependent
327                // instructions.
328                (*sd_it).second.pop_back();
329            }
330
331            waitingInsts.erase(waiting_it--);
332        }
333    }
334
335    if (!readyInsts.empty()) {
336        sn_it_t ready_it = readyInsts.end();
337
338        --ready_it;
339
340        // Same for the ready list.
341        while (!readyInsts.empty() &&
342               (*ready_it) > squashed_num)
343        {
344            readyInsts.erase(ready_it--);
345        }
346    }
347
348    if (!storeDependents.empty()) {
349        sd_it_t dep_it = storeDependents.end();
350
351        --dep_it;
352
353        // Same for the dependencies list.
354        while (!storeDependents.empty() &&
355               (*dep_it).first > squashed_num)
356        {
357            // This store's list of dependent instructions should be empty.
358            assert((*dep_it).second.empty());
359
360            storeDependents.erase(dep_it--);
361        }
362    }
363
364    // Tell the dependency predictor to squash as well.
365    depPred.squash(squashed_num);
366}
367
368template <class MemDepPred, class Impl>
369void
370MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
371                                        DynInstPtr &violating_load)
372{
373    DPRINTF(MemDepUnit, "MemDepUnit: Passing violating PCs to store sets,"
374            " load: %#x, store: %#x\n", violating_load->readPC(),
375            store_inst->readPC());
376    // Tell the memory dependence unit of the violation.
377    depPred.violation(violating_load->readPC(), store_inst->readPC());
378}
379
380template <class MemDepPred, class Impl>
381inline void
382MemDepUnit<MemDepPred, Impl>::moveToReady(dep_it_t &woken_inst)
383{
384    DPRINTF(MemDepUnit, "MemDepUnit: Adding instruction sequence number %i "
385            "to the ready list.\n", (*woken_inst).seqNum);
386
387    // Add it to the ready list.
388    readyInsts.insert((*woken_inst).seqNum);
389
390    // Remove it from the waiting instructions.
391    waitingInsts.erase(woken_inst);
392}
393