Deleted Added
sdiff udiff text old ( 2654:9559cfa91b9d ) new ( 2665:a124942bacb8 )
full compact
1/*
2 * Copyright (c) 2004-2005 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

--- 8 unchanged lines hidden (view full) ---

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 */
30
31// @todo: Fix the instantaneous communication among all the stages within
32// iew. There's a clear delay between issue and execute, yet backwards
33// communication happens simultaneously.
34// Update the statuses for each stage.
35
36#include <queue>
37
38#include "base/timebuf.hh"
39#include "cpu/o3/iew.hh"
40
41template<class Impl>
42SimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
43 SimpleIEW<Impl> *_iew)
44 : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
45{
46 this->setFlags(Event::AutoDelete);
47}
48
49template<class Impl>
50void
51SimpleIEW<Impl>::WritebackEvent::process()
52{
53 DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
54
55 // Need to insert instruction into queue to commit
56 iewStage->instToCommit(inst);
57 // Need to execute second half of the instruction, do actual writing to
58 // registers and such
59 inst->execute();
60}
61
62template<class Impl>
63const char *
64SimpleIEW<Impl>::WritebackEvent::description()
65{
66 return "LSQ writeback event";
67}
68
69template<class Impl>
70SimpleIEW<Impl>::SimpleIEW(Params &params)
71 : // Just make this time buffer really big for now
72 issueToExecQueue(5, 5),
73 instQueue(params),
74 ldstQueue(params),
75 commitToIEWDelay(params.commitToIEWDelay),
76 renameToIEWDelay(params.renameToIEWDelay),
77 issueToExecuteDelay(params.issueToExecuteDelay),
78 issueReadWidth(params.issueWidth),
79 issueWidth(params.issueWidth),
80 executeWidth(params.executeWidth)
81{
82 DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
83 _status = Idle;
84 _issueStatus = Idle;
85 _exeStatus = Idle;
86 _wbStatus = Idle;
87
88 // Setup wire to read instructions coming from issue.
89 fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
90
91 // Instruction queue needs the queue between issue and execute.
92 instQueue.setIssueToExecuteQueue(&issueToExecQueue);
93
94 ldstQueue.setIEW(this);
95}
96
97template <class Impl>
98void
99SimpleIEW<Impl>::regStats()
100{
101 instQueue.regStats();
102
103 iewIdleCycles
104 .name(name() + ".iewIdleCycles")
105 .desc("Number of cycles IEW is idle");
106
107 iewSquashCycles
108 .name(name() + ".iewSquashCycles")
109 .desc("Number of cycles IEW is squashing");
110
111 iewBlockCycles
112 .name(name() + ".iewBlockCycles")
113 .desc("Number of cycles IEW is blocking");
114
115 iewUnblockCycles
116 .name(name() + ".iewUnblockCycles")
117 .desc("Number of cycles IEW is unblocking");
118
119// iewWBInsts;
120
121 iewDispatchedInsts
122 .name(name() + ".iewDispatchedInsts")
123 .desc("Number of instructions dispatched to IQ");
124
125 iewDispSquashedInsts
126 .name(name() + ".iewDispSquashedInsts")
127 .desc("Number of squashed instructions skipped by dispatch");
128

--- 8 unchanged lines hidden (view full) ---

137 iewDispNonSpecInsts
138 .name(name() + ".iewDispNonSpecInsts")
139 .desc("Number of dispatched non-speculative instructions");
140
141 iewIQFullEvents
142 .name(name() + ".iewIQFullEvents")
143 .desc("Number of times the IQ has become full, causing a stall");
144
145 iewExecutedInsts
146 .name(name() + ".iewExecutedInsts")
147 .desc("Number of executed instructions");
148
149 iewExecLoadInsts
150 .name(name() + ".iewExecLoadInsts")
151 .desc("Number of load instructions executed");
152
153 iewExecStoreInsts
154 .name(name() + ".iewExecStoreInsts")
155 .desc("Number of store instructions executed");
156
157 iewExecSquashedInsts
158 .name(name() + ".iewExecSquashedInsts")
159 .desc("Number of squashed instructions skipped in execute");
160
161 memOrderViolationEvents
162 .name(name() + ".memOrderViolationEvents")
163 .desc("Number of memory order violations");
164
165 predictedTakenIncorrect
166 .name(name() + ".predictedTakenIncorrect")
167 .desc("Number of branches that were predicted taken incorrectly");
168}
169
170template<class Impl>
171void
172SimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
173{
174 DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
175 cpu = cpu_ptr;
176
177 instQueue.setCPU(cpu_ptr);
178 ldstQueue.setCPU(cpu_ptr);
179}
180
181template<class Impl>
182void
183SimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
184{
185 DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
186 timeBuffer = tb_ptr;
187
188 // Setup wire to read information from time buffer, from commit.
189 fromCommit = timeBuffer->getWire(-commitToIEWDelay);
190
191 // Setup wire to write information back to previous stages.
192 toRename = timeBuffer->getWire(0);
193
194 // Instruction queue also needs main time buffer.
195 instQueue.setTimeBuffer(tb_ptr);
196}
197
198template<class Impl>
199void
200SimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
201{
202 DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
203 renameQueue = rq_ptr;
204
205 // Setup wire to read information from rename queue.
206 fromRename = renameQueue->getWire(-renameToIEWDelay);
207}
208
209template<class Impl>
210void
211SimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
212{
213 DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
214 iewQueue = iq_ptr;
215
216 // Setup wire to write instructions to commit.
217 toCommit = iewQueue->getWire(0);
218}
219
220template<class Impl>
221void
222SimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
223{
224 DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
225 renameMap = rm_ptr;
226}
227
228template<class Impl>
229void
230SimpleIEW<Impl>::squash()
231{
232 DPRINTF(IEW, "IEW: Squashing all instructions.\n");
233 _status = Squashing;
234
235 // Tell the IQ to start squashing.
236 instQueue.squash();
237
238 // Tell the LDSTQ to start squashing.
239 ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
240}
241
242template<class Impl>
243void
244SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
245{
246 DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
247 inst->PC);
248 // Perhaps leave the squashing up to the ROB stage to tell it when to
249 // squash?
250 _status = Squashing;
251
252 // Tell rename to squash through the time buffer.
253 toCommit->squash = true;
254 // Also send PC update information back to prior stages.
255 toCommit->squashedSeqNum = inst->seqNum;
256 toCommit->mispredPC = inst->readPC();
257 toCommit->nextPC = inst->readNextPC();
258 toCommit->branchMispredict = true;
259 // Prediction was incorrect, so send back inverse.
260 toCommit->branchTaken = inst->readNextPC() !=
261 (inst->readPC() + sizeof(TheISA::MachInst));
262}
263
264template<class Impl>
265void
266SimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
267{
268 DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
269 inst->PC);
270 // Perhaps leave the squashing up to the ROB stage to tell it when to
271 // squash?
272 _status = Squashing;
273
274 // Tell rename to squash through the time buffer.
275 toCommit->squash = true;
276 // Also send PC update information back to prior stages.
277 toCommit->squashedSeqNum = inst->seqNum;
278 toCommit->nextPC = inst->readNextPC();
279}
280
281template<class Impl>
282void
283SimpleIEW<Impl>::block()
284{
285 DPRINTF(IEW, "IEW: Blocking.\n");
286 // Set the status to Blocked.
287 _status = Blocked;
288
289 // Add the current inputs to the skid buffer so they can be
290 // reprocessed when this stage unblocks.
291 skidBuffer.push(*fromRename);
292
293 // Note that this stage only signals previous stages to stall when
294 // it is the cause of the stall originates at this stage. Otherwise
295 // the previous stages are expected to check all possible stall signals.
296}
297
298template<class Impl>
299inline void
300SimpleIEW<Impl>::unblock()
301{
302 // Check if there's information in the skid buffer. If there is, then
303 // set status to unblocking, otherwise set it directly to running.
304 DPRINTF(IEW, "IEW: Reading instructions out of the skid "
305 "buffer.\n");
306 // Remove the now processed instructions from the skid buffer.
307 skidBuffer.pop();
308
309 // If there's still information in the skid buffer, then
310 // continue to tell previous stages to stall. They will be
311 // able to restart once the skid buffer is empty.
312 if (!skidBuffer.empty()) {
313 toRename->iewInfo.stall = true;
314 } else {
315 DPRINTF(IEW, "IEW: Stage is done unblocking.\n");
316 _status = Running;
317 }
318}
319
320template<class Impl>
321void
322SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
323{
324 instQueue.wakeDependents(inst);
325}
326
327
328template<class Impl>
329void
330SimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
331{
332
333}
334
335template <class Impl>
336void
337SimpleIEW<Impl>::dispatchInsts()
338{
339 ////////////////////////////////////////
340 // DISPATCH/ISSUE stage
341 ////////////////////////////////////////
342
343 //Put into its own function?
344 //Add instructions to IQ if there are any instructions there
345
346 // Check if there are any instructions coming from rename, and we're.
347 // not squashing.
348 if (fromRename->size > 0) {
349 int insts_to_add = fromRename->size;
350
351 // Loop through the instructions, putting them in the instruction
352 // queue.
353 for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)
354 {
355 DynInstPtr inst = fromRename->insts[inst_num];
356
357 // Make sure there's a valid instruction there.
358 assert(inst);
359
360 DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
361 inst->readPC());
362
363 // Be sure to mark these instructions as ready so that the
364 // commit stage can go ahead and execute them, and mark
365 // them as issued so the IQ doesn't reprocess them.
366 if (inst->isSquashed()) {
367 ++iewDispSquashedInsts;
368 continue;
369 } else if (instQueue.isFull()) {
370 DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
371 // Call function to start blocking.
372 block();
373 // Tell previous stage to stall.
374 toRename->iewInfo.stall = true;
375
376 ++iewIQFullEvents;
377 break;
378 } else if (inst->isLoad()) {
379 DPRINTF(IEW, "IEW: Issue: Memory instruction "
380 "encountered, adding to LDSTQ.\n");
381
382 // Reserve a spot in the load store queue for this
383 // memory access.
384 ldstQueue.insertLoad(inst);
385
386 ++iewDispLoadInsts;
387 } else if (inst->isStore()) {
388 ldstQueue.insertStore(inst);
389
390 ++iewDispStoreInsts;
391 } else if (inst->isNonSpeculative()) {
392 DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
393 "encountered, skipping.\n");
394
395 // Same hack as with stores.
396 inst->setCanCommit();
397
398 // Specificall insert it as nonspeculative.
399 instQueue.insertNonSpec(inst);
400
401 ++iewDispNonSpecInsts;
402
403 continue;
404 } else if (inst->isNop()) {
405 DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
406 ", skipping.\n");
407
408 inst->setIssued();
409 inst->setExecuted();
410 inst->setCanCommit();
411
412 instQueue.advanceTail(inst);
413
414 continue;
415 } else if (inst->isExecuted()) {
416 assert(0 && "Instruction shouldn't be executed.\n");
417 DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
418 "skipping.\n");
419
420 inst->setIssued();
421 inst->setCanCommit();
422
423 instQueue.advanceTail(inst);
424
425 continue;
426 }
427
428 // If the instruction queue is not full, then add the
429 // instruction.
430 instQueue.insert(fromRename->insts[inst_num]);
431
432 ++iewDispatchedInsts;
433 }
434 }
435}
436
437template <class Impl>
438void
439SimpleIEW<Impl>::executeInsts()
440{
441 ////////////////////////////////////////
442 //EXECUTE/WRITEBACK stage
443 ////////////////////////////////////////
444
445 //Put into its own function?
446 //Similarly should probably have separate execution for int vs FP.
447 // Above comment is handled by the issue queue only issuing a valid
448 // mix of int/fp instructions.
449 //Actually okay to just have one execution, buuuuuut will need
450 //somewhere that defines the execution latency of all instructions.
451 // @todo: Move to the FU pool used in the current full cpu.
452
453 int fu_usage = 0;
454 bool fetch_redirect = false;
455 int inst_slot = 0;
456 int time_slot = 0;
457
458 // Execute/writeback any instructions that are available.
459 for (int inst_num = 0;
460 fu_usage < executeWidth && /* Haven't exceeded available FU's. */
461 inst_num < issueWidth &&
462 fromIssue->insts[inst_num];
463 ++inst_num) {
464
465 DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
466
467 // Get instruction from issue's queue.
468 DynInstPtr inst = fromIssue->insts[inst_num];
469
470 DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
471
472 // Check if the instruction is squashed; if so then skip it
473 // and don't count it towards the FU usage.
474 if (inst->isSquashed()) {
475 DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
476
477 // Consider this instruction executed so that commit can go
478 // ahead and retire the instruction.
479 inst->setExecuted();
480
481 toCommit->insts[inst_num] = inst;
482
483 ++iewExecSquashedInsts;
484
485 continue;
486 }
487
488 inst->setExecuted();
489
490 // If an instruction is executed, then count it towards FU usage.
491 ++fu_usage;
492
493 // Execute instruction.
494 // Note that if the instruction faults, it will be handled
495 // at the commit stage.
496 if (inst->isMemRef()) {
497 DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
498 "reference.\n");
499
500 // Tell the LDSTQ to execute this instruction (if it is a load).
501 if (inst->isLoad()) {
502 ldstQueue.executeLoad(inst);
503
504 ++iewExecLoadInsts;
505 } else if (inst->isStore()) {
506 ldstQueue.executeStore(inst);
507
508 ++iewExecStoreInsts;
509 } else {
510 panic("IEW: Unexpected memory type!\n");
511 }
512
513 } else {
514 inst->execute();
515
516 ++iewExecutedInsts;
517 }
518
519 // First check the time slot that this instruction will write
520 // to. If there are free write ports at the time, then go ahead
521 // and write the instruction to that time. If there are not,
522 // keep looking back to see where's the first time there's a
523 // free slot. What happens if you run out of free spaces?
524 // For now naively assume that all instructions take one cycle.
525 // Otherwise would have to look into the time buffer based on the
526 // latency of the instruction.
527 (*iewQueue)[time_slot].insts[inst_slot];
528 while ((*iewQueue)[time_slot].insts[inst_slot]) {
529 if (inst_slot < issueWidth) {
530 ++inst_slot;
531 } else {
532 ++time_slot;
533 inst_slot = 0;
534 }
535
536 assert(time_slot < 5);
537 }
538
539 // May actually have to work this out, especially with loads and stores
540
541 // Add finished instruction to queue to commit.
542 (*iewQueue)[time_slot].insts[inst_slot] = inst;
543 (*iewQueue)[time_slot].size++;
544
545 // Check if branch was correct. This check happens after the
546 // instruction is added to the queue because even if the branch
547 // is mispredicted, the branch instruction itself is still valid.
548 // Only handle this if there hasn't already been something that
549 // redirects fetch in this group of instructions.
550 if (!fetch_redirect) {
551 if (inst->mispredicted()) {
552 fetch_redirect = true;
553
554 DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
555 DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
556 inst->nextPC);
557
558 // If incorrect, then signal the ROB that it must be squashed.
559 squashDueToBranch(inst);
560
561 if (inst->predTaken()) {
562 predictedTakenIncorrect++;
563 }
564 } else if (ldstQueue.violation()) {
565 fetch_redirect = true;
566
567 // Get the DynInst that caused the violation.
568 DynInstPtr violator = ldstQueue.getMemDepViolator();
569
570 DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: "
571 "%#x, inst PC: %#x. Addr is: %#x.\n",
572 violator->readPC(), inst->readPC(), inst->physEffAddr);
573
574 // Tell the instruction queue that a violation has occured.
575 instQueue.violation(inst, violator);
576
577 // Squash.
578 squashDueToMem(inst);
579
580 ++memOrderViolationEvents;
581 }
582 }
583 }
584}
585
586template
587void
588SimpleIEW<Impl>::tick()
589{
590 // Considering putting all the state-determining stuff in this section.
591
592 // Try to fill up issue queue with as many instructions as bandwidth
593 // allows.
594 // Decode should try to execute as many instructions as its bandwidth
595 // will allow, as long as it is not currently blocked.
596
597 // Check if the stage is in a running status.
598 if (_status != Blocked && _status != Squashing) {
599 DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
600 "stage.\n");
601 iew();
602
603 // If it's currently unblocking, check to see if it should switch
604 // to running.
605 if (_status == Unblocking) {
606 unblock();
607
608 ++iewUnblockCycles;
609 }
610 } else if (_status == Squashing) {
611
612 DPRINTF(IEW, "IEW: Still squashing.\n");
613
614 // Check if stage should remain squashing. Stop squashing if the
615 // squash signal clears.
616 if (!fromCommit->commitInfo.squash &&
617 !fromCommit->commitInfo.robSquashing) {
618 DPRINTF(IEW, "IEW: Done squashing, changing status to "
619 "running.\n");
620
621 _status = Running;
622 instQueue.stopSquash();
623 } else {
624 instQueue.doSquash();
625 }
626
627 ++iewSquashCycles;
628 } else if (_status == Blocked) {
629 // Continue to tell previous stage to stall.
630 toRename->iewInfo.stall = true;
631
632 // Check if possible stall conditions have cleared.
633 if (!fromCommit->commitInfo.stall &&
634 !instQueue.isFull()) {
635 DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
636 _status = Unblocking;
637 }
638
639 // If there's still instructions coming from rename, continue to
640 // put them on the skid buffer.
641 if (fromRename->size == 0) {
642 block();
643 }
644
645 if (fromCommit->commitInfo.squash ||
646 fromCommit->commitInfo.robSquashing) {
647 squash();
648 }
649
650 ++iewBlockCycles;
651 }
652
653 // @todo: Maybe put these at the beginning, so if it's idle it can
654 // return early.
655 // Write back number of free IQ entries here.
656 toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
657
658 ldstQueue.writebackStores();
659
660 // Check the committed load/store signals to see if there's a load
661 // or store to commit. Also check if it's being told to execute a
662 // nonspeculative instruction.
663 // This is pretty inefficient...
664 if (!fromCommit->commitInfo.squash &&
665 !fromCommit->commitInfo.robSquashing) {
666 ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
667 ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
668 }
669
670 if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
671 instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
672 }
673
674 DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
675 instQueue.numFreeEntries());
676}
677
678template<class Impl>
679void
680SimpleIEW<Impl>::iew()
681{
682 // Might want to put all state checks in the tick() function.
683 // Check if being told to stall from commit.
684 if (fromCommit->commitInfo.stall) {
685 block();
686 return;
687 } else if (fromCommit->commitInfo.squash ||
688 fromCommit->commitInfo.robSquashing) {
689 // Also check if commit is telling this stage to squash.
690 squash();
691 return;
692 }
693
694 dispatchInsts();
695
696 // Have the instruction queue try to schedule any ready instructions.
697 instQueue.scheduleReadyInsts();
698
699 executeInsts();
700
701 // Loop through the head of the time buffer and wake any dependents.
702 // These instructions are about to write back. In the simple model
703 // this loop can really happen within the previous loop, but when
704 // instructions have actual latencies, this loop must be separate.
705 // Also mark scoreboard that this instruction is finally complete.
706 // Either have IEW have direct access to rename map, or have this as
707 // part of backwards communication.
708 for (int inst_num = 0; inst_num < issueWidth &&
709 toCommit->insts[inst_num]; inst_num++)
710 {
711 DynInstPtr inst = toCommit->insts[inst_num];
712
713 DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
714 inst->readPC());
715
716 if(!inst->isSquashed()) {
717 instQueue.wakeDependents(inst);
718
719 for (int i = 0; i < inst->numDestRegs(); i++)
720 {
721 renameMap->markAsReady(inst->renamedDestRegIdx(i));
722 }
723 }
724 }
725
726 // Also should advance its own time buffers if the stage ran.
727 // Not the best place for it, but this works (hopefully).
728 issueToExecQueue.advance();
729}
730
731#if !FULL_SYSTEM
732template<class Impl>
733void
734SimpleIEW<Impl>::lsqWriteback()
735{
736 ldstQueue.writebackAllInsts();
737}
738#endif