iew_impl.hh revision 1062
1// @todo: Fix the instantaneous communication among all the stages within
2// iew.  There's a clear delay between issue and execute, yet backwards
3// communication happens simultaneously.  Might not be that bad really...
4// it might skew stats a bit though.  Issue would otherwise try to issue
5// instructions that would never be executed if there were a delay; without
6// it issue will simply squash.  Make this stage block properly.
7// Update the statuses for each stage.
8// Actually read instructions out of the skid buffer.
9
10#include <queue>
11
12#include "base/timebuf.hh"
13#include "cpu/beta_cpu/iew.hh"
14
15template<class Impl, class IQ>
16SimpleIEW<Impl, IQ>::SimpleIEW(Params &params)
17    : // Just make this time buffer really big for now
18      issueToExecQueue(5, 5),
19      instQueue(params),
20      ldstQueue(params),
21      commitToIEWDelay(params.commitToIEWDelay),
22      renameToIEWDelay(params.renameToIEWDelay),
23      issueToExecuteDelay(params.issueToExecuteDelay),
24      issueReadWidth(params.issueWidth),
25      issueWidth(params.issueWidth),
26      executeWidth(params.executeWidth)
27{
28    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
29    _status = Idle;
30    _issueStatus = Idle;
31    _exeStatus = Idle;
32    _wbStatus = Idle;
33
34    // Setup wire to read instructions coming from issue.
35    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
36
37    // Instruction queue needs the queue between issue and execute.
38    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
39}
40
41template <class Impl, class IQ>
42void
43SimpleIEW<Impl, IQ>::regStats()
44{
45    instQueue.regStats();
46
47    iewIdleCycles
48        .name(name() + ".iewIdleCycles")
49        .desc("Number of cycles IEW is idle");
50
51    iewSquashCycles
52        .name(name() + ".iewSquashCycles")
53        .desc("Number of cycles IEW is squashing");
54
55    iewBlockCycles
56        .name(name() + ".iewBlockCycles")
57        .desc("Number of cycles IEW is blocking");
58
59    iewUnblockCycles
60        .name(name() + ".iewUnblockCycles")
61        .desc("Number of cycles IEW is unblocking");
62
63//    iewWBInsts;
64
65    iewDispatchedInsts
66        .name(name() + ".iewDispatchedInsts")
67        .desc("Number of instructions dispatched to IQ");
68
69    iewDispSquashedInsts
70        .name(name() + ".iewDispSquashedInsts")
71        .desc("Number of squashed instructions skipped by dispatch");
72
73    iewDispLoadInsts
74        .name(name() + ".iewDispLoadInsts")
75        .desc("Number of dispatched load instructions");
76
77    iewDispStoreInsts
78        .name(name() + ".iewDispStoreInsts")
79        .desc("Number of dispatched store instructions");
80
81    iewDispNonSpecInsts
82        .name(name() + ".iewDispNonSpecInsts")
83        .desc("Number of dispatched non-speculative instructions");
84
85    iewIQFullEvents
86        .name(name() + ".iewIQFullEvents")
87        .desc("Number of times the IQ has become full, causing a stall");
88
89    iewExecutedInsts
90        .name(name() + ".iewExecutedInsts")
91        .desc("Number of executed instructions");
92
93    iewExecLoadInsts
94        .name(name() + ".iewExecLoadInsts")
95        .desc("Number of load instructions executed");
96
97    iewExecStoreInsts
98        .name(name() + ".iewExecStoreInsts")
99        .desc("Number of store instructions executed");
100
101    iewExecSquashedInsts
102        .name(name() + ".iewExecSquashedInsts")
103        .desc("Number of squashed instructions skipped in execute");
104
105    memOrderViolationEvents
106        .name(name() + ".memOrderViolationEvents")
107        .desc("Number of memory order violations");
108
109    predictedTakenIncorrect
110        .name(name() + ".predictedTakenIncorrect")
111        .desc("Number of branches that were predicted taken incorrectly");
112}
113
114template<class Impl, class IQ>
115void
116SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr)
117{
118    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
119    cpu = cpu_ptr;
120
121    instQueue.setCPU(cpu_ptr);
122    ldstQueue.setCPU(cpu_ptr);
123}
124
125template<class Impl, class IQ>
126void
127SimpleIEW<Impl, IQ>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
128{
129    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
130    timeBuffer = tb_ptr;
131
132    // Setup wire to read information from time buffer, from commit.
133    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
134
135    // Setup wire to write information back to previous stages.
136    toRename = timeBuffer->getWire(0);
137
138    // Instruction queue also needs main time buffer.
139    instQueue.setTimeBuffer(tb_ptr);
140}
141
142template<class Impl, class IQ>
143void
144SimpleIEW<Impl, IQ>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
145{
146    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
147    renameQueue = rq_ptr;
148
149    // Setup wire to read information from rename queue.
150    fromRename = renameQueue->getWire(-renameToIEWDelay);
151}
152
153template<class Impl, class IQ>
154void
155SimpleIEW<Impl, IQ>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
156{
157    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
158    iewQueue = iq_ptr;
159
160    // Setup wire to write instructions to commit.
161    toCommit = iewQueue->getWire(0);
162}
163
164template<class Impl, class IQ>
165void
166SimpleIEW<Impl, IQ>::setRenameMap(RenameMap *rm_ptr)
167{
168    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
169    renameMap = rm_ptr;
170}
171
172template<class Impl, class IQ>
173void
174SimpleIEW<Impl, IQ>::wakeDependents(DynInstPtr &inst)
175{
176    instQueue.wakeDependents(inst);
177}
178
179template<class Impl, class IQ>
180void
181SimpleIEW<Impl, IQ>::block()
182{
183    DPRINTF(IEW, "IEW: Blocking.\n");
184    // Set the status to Blocked.
185    _status = Blocked;
186
187    // Add the current inputs to the skid buffer so they can be
188    // reprocessed when this stage unblocks.
189    skidBuffer.push(*fromRename);
190
191    // Note that this stage only signals previous stages to stall when
192    // it is the cause of the stall originates at this stage.  Otherwise
193    // the previous stages are expected to check all possible stall signals.
194}
195
196template<class Impl, class IQ>
197inline void
198SimpleIEW<Impl, IQ>::unblock()
199{
200    // Check if there's information in the skid buffer.  If there is, then
201    // set status to unblocking, otherwise set it directly to running.
202    DPRINTF(IEW, "IEW: Reading instructions out of the skid "
203            "buffer.\n");
204    // Remove the now processed instructions from the skid buffer.
205    skidBuffer.pop();
206
207    // If there's still information in the skid buffer, then
208    // continue to tell previous stages to stall.  They will be
209    // able to restart once the skid buffer is empty.
210    if (!skidBuffer.empty()) {
211        toRename->iewInfo.stall = true;
212    } else {
213        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
214        _status = Running;
215    }
216}
217
218template<class Impl, class IQ>
219void
220SimpleIEW<Impl, IQ>::squash()
221{
222    DPRINTF(IEW, "IEW: Squashing all instructions.\n");
223    _status = Squashing;
224
225    // Tell the IQ to start squashing.
226    instQueue.squash();
227
228    // Tell the LDSTQ to start squashing.
229    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
230}
231
232template<class Impl, class IQ>
233void
234SimpleIEW<Impl, IQ>::squashDueToBranch(DynInstPtr &inst)
235{
236    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
237            inst->PC);
238    // Perhaps leave the squashing up to the ROB stage to tell it when to
239    // squash?
240    _status = Squashing;
241
242    // Tell rename to squash through the time buffer.
243    toCommit->squash = true;
244    // Also send PC update information back to prior stages.
245    toCommit->squashedSeqNum = inst->seqNum;
246    toCommit->mispredPC = inst->readPC();
247    toCommit->nextPC = inst->readCalcTarg();
248    toCommit->branchMispredict = true;
249    // Prediction was incorrect, so send back inverse.
250    toCommit->branchTaken = inst->readCalcTarg() !=
251        (inst->readPC() + sizeof(MachInst));
252//    toCommit->globalHist = inst->readGlobalHist();
253}
254
255template<class Impl, class IQ>
256void
257SimpleIEW<Impl, IQ>::squashDueToMem(DynInstPtr &inst)
258{
259    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
260            inst->PC);
261    // Perhaps leave the squashing up to the ROB stage to tell it when to
262    // squash?
263    _status = Squashing;
264
265    // Tell rename to squash through the time buffer.
266    toCommit->squash = true;
267    // Also send PC update information back to prior stages.
268    toCommit->squashedSeqNum = inst->seqNum;
269    toCommit->nextPC = inst->readCalcTarg();
270}
271
272template <class Impl, class IQ>
273void
274SimpleIEW<Impl, IQ>::dispatchInsts()
275{
276    ////////////////////////////////////////
277    // DISPATCH/ISSUE stage
278    ////////////////////////////////////////
279
280    //Put into its own function?
281    //Add instructions to IQ if there are any instructions there
282
283    // Check if there are any instructions coming from rename, and we're.
284    // not squashing.
285    if (fromRename->size > 0) {
286        int insts_to_add = fromRename->size;
287
288        // Loop through the instructions, putting them in the instruction
289        // queue.
290        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
291        {
292            DynInstPtr inst = fromRename->insts[inst_num];
293
294            // Make sure there's a valid instruction there.
295            assert(inst);
296
297            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
298                    inst->readPC());
299
300            // Be sure to mark these instructions as ready so that the
301            // commit stage can go ahead and execute them, and mark
302            // them as issued so the IQ doesn't reprocess them.
303            if (inst->isSquashed()) {
304                ++iewDispSquashedInsts;
305                continue;
306            } else if (instQueue.isFull()) {
307                DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
308                // Call function to start blocking.
309                block();
310                // Tell previous stage to stall.
311                toRename->iewInfo.stall = true;
312
313                ++iewIQFullEvents;
314                break;
315            } else if (inst->isLoad()) {
316                DPRINTF(IEW, "IEW: Issue: Memory instruction "
317                        "encountered, adding to LDSTQ.\n");
318
319                // Reserve a spot in the load store queue for this
320                // memory access.
321                ldstQueue.insertLoad(inst);
322
323                ++iewDispLoadInsts;
324            } else if (inst->isStore()) {
325                ldstQueue.insertStore(inst);
326
327                // A bit of a hack.  Set that it can commit so that
328                // the commit stage will try committing it, and then
329                // once commit realizes it's a store it will send back
330                // a signal to this stage to issue and execute that
331                // store.  Change to be a bit that says the instruction
332                // has extra work to do at commit.
333                inst->setCanCommit();
334
335                instQueue.insertNonSpec(inst);
336
337                ++iewDispStoreInsts;
338                ++iewDispNonSpecInsts;
339
340                continue;
341            } else if (inst->isNonSpeculative()) {
342                DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
343                        "encountered, skipping.\n");
344
345                // Same hack as with stores.
346                inst->setCanCommit();
347
348                // Specificall insert it as nonspeculative.
349                instQueue.insertNonSpec(inst);
350
351                ++iewDispNonSpecInsts;
352
353                continue;
354            } else if (inst->isNop()) {
355                DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
356                        ", skipping.\n");
357
358                inst->setIssued();
359                inst->setExecuted();
360                inst->setCanCommit();
361
362                instQueue.advanceTail(inst);
363
364                continue;
365            } else if (inst->isExecuted()) {
366                DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
367                        "skipping.\n");
368
369                assert(inst->isDirectCtrl());
370
371                inst->setIssued();
372                inst->setCanCommit();
373
374                instQueue.advanceTail(inst);
375
376                continue;
377            }
378
379            // If the instruction queue is not full, then add the
380            // instruction.
381            instQueue.insert(fromRename->insts[inst_num]);
382
383            ++iewDispatchedInsts;
384        }
385    }
386}
387
388template <class Impl, class IQ>
389void
390SimpleIEW<Impl, IQ>::executeInsts()
391{
392    ////////////////////////////////////////
393    //EXECUTE/WRITEBACK stage
394    ////////////////////////////////////////
395
396    //Put into its own function?
397    //Similarly should probably have separate execution for int vs FP.
398    // Above comment is handled by the issue queue only issuing a valid
399    // mix of int/fp instructions.
400    //Actually okay to just have one execution, buuuuuut will need
401    //somewhere that defines the execution latency of all instructions.
402    // @todo: Move to the FU pool used in the current full cpu.
403
404    int fu_usage = 0;
405    bool fetch_redirect = false;
406
407    // Execute/writeback any instructions that are available.
408    for (int inst_num = 0;
409         fu_usage < executeWidth && /* Haven't exceeded available FU's. */
410             inst_num < issueWidth &&
411             fromIssue->insts[inst_num];
412         ++inst_num) {
413
414        DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
415
416        // Get instruction from issue's queue.
417        DynInstPtr inst = fromIssue->insts[inst_num];
418
419        DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
420
421        // Check if the instruction is squashed; if so then skip it
422        // and don't count it towards the FU usage.
423        if (inst->isSquashed()) {
424            DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
425
426            // Consider this instruction executed so that commit can go
427            // ahead and retire the instruction.
428            inst->setExecuted();
429
430            toCommit->insts[inst_num] = inst;
431
432            ++iewExecSquashedInsts;
433
434            continue;
435        }
436
437        inst->setExecuted();
438
439        // If an instruction is executed, then count it towards FU usage.
440        ++fu_usage;
441
442        // Execute instruction.
443        // Note that if the instruction faults, it will be handled
444        // at the commit stage.
445        if (inst->isMemRef()) {
446            DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
447                    "reference.\n");
448
449            // Tell the LDSTQ to execute this instruction (if it is a load).
450            if (inst->isLoad()) {
451                ldstQueue.executeLoad(inst);
452
453                ++iewExecLoadInsts;
454            } else if (inst->isStore()) {
455                ldstQueue.executeStore();
456
457                ++iewExecStoreInsts;
458            } else {
459                panic("IEW: Unexpected memory type!\n");
460            }
461
462        } else {
463            inst->execute();
464
465            ++iewExecutedInsts;
466        }
467
468        // First check the time slot that this instruction will write
469        // to.  If there are free write ports at the time, then go ahead
470        // and write the instruction to that time.  If there are not,
471        // keep looking back to see where's the first time there's a
472        // free slot.  What happens if you run out of free spaces?
473        // For now naively assume that all instructions take one cycle.
474        // Otherwise would have to look into the time buffer based on the
475        // latency of the instruction.
476
477        // Add finished instruction to queue to commit.
478        toCommit->insts[inst_num] = inst;
479
480        // Check if branch was correct.  This check happens after the
481        // instruction is added to the queue because even if the branch
482        // is mispredicted, the branch instruction itself is still valid.
483        // Only handle this if there hasn't already been something that
484        // redirects fetch in this group of instructions.
485        if (!fetch_redirect) {
486            if (inst->mispredicted()) {
487                fetch_redirect = true;
488
489                DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
490                DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
491                        inst->nextPC);
492
493                // If incorrect, then signal the ROB that it must be squashed.
494                squashDueToBranch(inst);
495
496                if (inst->predTaken()) {
497                    predictedTakenIncorrect++;
498                }
499            } else if (ldstQueue.violation()) {
500                fetch_redirect = true;
501
502                // Get the DynInst that caused the violation.
503                DynInstPtr violator = ldstQueue.getMemDepViolator();
504
505                DPRINTF(IEW, "IEW: LDSTQ detected a violation.  Violator PC: "
506                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
507                        violator->readPC(), inst->readPC(), inst->physEffAddr);
508
509                // Tell the instruction queue that a violation has occured.
510                instQueue.violation(inst, violator);
511
512                // Squash.
513                squashDueToMem(inst);
514
515                ++memOrderViolationEvents;
516            }
517        }
518    }
519}
520
521template<class Impl, class IQ>
522void
523SimpleIEW<Impl, IQ>::tick()
524{
525    // Considering putting all the state-determining stuff in this section.
526
527    // Try to fill up issue queue with as many instructions as bandwidth
528    // allows.
529    // Decode should try to execute as many instructions as its bandwidth
530    // will allow, as long as it is not currently blocked.
531
532    // Check if the stage is in a running status.
533    if (_status != Blocked && _status != Squashing) {
534        DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
535                     "stage.\n");
536        iew();
537
538        // If it's currently unblocking, check to see if it should switch
539        // to running.
540        if (_status == Unblocking) {
541            unblock();
542
543            ++iewUnblockCycles;
544        }
545    } else if (_status == Squashing) {
546
547        DPRINTF(IEW, "IEW: Still squashing.\n");
548
549        // Check if stage should remain squashing.  Stop squashing if the
550        // squash signal clears.
551        if (!fromCommit->commitInfo.squash &&
552            !fromCommit->commitInfo.robSquashing) {
553            DPRINTF(IEW, "IEW: Done squashing, changing status to "
554                    "running.\n");
555
556            _status = Running;
557            instQueue.stopSquash();
558        } else {
559            instQueue.doSquash();
560        }
561
562        ++iewSquashCycles;
563
564        // Also should advance its own time buffers if the stage ran.
565        // Not sure about this...
566//        issueToExecQueue.advance();
567    } else if (_status == Blocked) {
568        // Continue to tell previous stage to stall.
569        toRename->iewInfo.stall = true;
570
571        // Check if possible stall conditions have cleared.
572        if (!fromCommit->commitInfo.stall &&
573            !instQueue.isFull()) {
574            DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
575            _status = Unblocking;
576        }
577
578        // If there's still instructions coming from rename, continue to
579        // put them on the skid buffer.
580        if (fromRename->size == 0) {
581            block();
582        }
583
584        if (fromCommit->commitInfo.squash ||
585            fromCommit->commitInfo.robSquashing) {
586            squash();
587        }
588
589        ++iewBlockCycles;
590    }
591
592    // @todo: Maybe put these at the beginning, so if it's idle it can
593    // return early.
594    // Write back number of free IQ entries here.
595    toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
596
597    // Check the committed load/store signals to see if there's a load
598    // or store to commit.  Also check if it's being told to execute a
599    // nonspeculative instruction.
600    if (fromCommit->commitInfo.commitIsStore) {
601        ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
602    } else if (fromCommit->commitInfo.commitIsLoad) {
603        ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
604    }
605
606    if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
607        instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
608    }
609
610    DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
611            instQueue.numFreeEntries());
612}
613
614template<class Impl, class IQ>
615void
616SimpleIEW<Impl, IQ>::iew()
617{
618    // Might want to put all state checks in the tick() function.
619    // Check if being told to stall from commit.
620    if (fromCommit->commitInfo.stall) {
621        block();
622        return;
623    } else if (fromCommit->commitInfo.squash ||
624               fromCommit->commitInfo.robSquashing) {
625        // Also check if commit is telling this stage to squash.
626        squash();
627        return;
628    }
629
630    dispatchInsts();
631
632    // Have the instruction queue try to schedule any ready instructions.
633    instQueue.scheduleReadyInsts();
634
635    executeInsts();
636
637    // Loop through the head of the time buffer and wake any dependents.
638    // These instructions are about to write back.  In the simple model
639    // this loop can really happen within the previous loop, but when
640    // instructions have actual latencies, this loop must be separate.
641    // Also mark scoreboard that this instruction is finally complete.
642    // Either have IEW have direct access to rename map, or have this as
643    // part of backwards communication.
644    for (int inst_num = 0; inst_num < issueWidth &&
645             toCommit->insts[inst_num]; inst_num++)
646    {
647        DynInstPtr inst = toCommit->insts[inst_num];
648
649        DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
650                inst->readPC());
651
652        if(!inst->isSquashed()) {
653            instQueue.wakeDependents(inst);
654
655            for (int i = 0; i < inst->numDestRegs(); i++)
656            {
657                renameMap->markAsReady(inst->renamedDestRegIdx(i));
658            }
659        }
660    }
661
662    // Also should advance its own time buffers if the stage ran.
663    // Not the best place for it, but this works (hopefully).
664    issueToExecQueue.advance();
665}
666