diff options
Diffstat (limited to 'cpu/beta_cpu/iew_impl.hh')
-rw-r--r-- | cpu/beta_cpu/iew_impl.hh | 229 |
1 files changed, 149 insertions, 80 deletions
diff --git a/cpu/beta_cpu/iew_impl.hh b/cpu/beta_cpu/iew_impl.hh index 1d072ab33..086d39320 100644 --- a/cpu/beta_cpu/iew_impl.hh +++ b/cpu/beta_cpu/iew_impl.hh @@ -12,8 +12,36 @@ #include "base/timebuf.hh" #include "cpu/beta_cpu/iew.hh" -template<class Impl, class IQ> -SimpleIEW<Impl, IQ>::SimpleIEW(Params ¶ms) +template<class Impl> +SimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, + SimpleIEW<Impl> *_iew) + : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew) +{ + this->setFlags(Event::AutoDelete); +} + +template<class Impl> +void +SimpleIEW<Impl>::WritebackEvent::process() +{ + DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n"); + + // Need to insert instruction into queue to commit + iewStage->instToCommit(inst); + // Need to execute second half of the instruction, do actual writing to + // registers and such + inst->execute(); +} + +template<class Impl> +const char * +SimpleIEW<Impl>::WritebackEvent::description() +{ + return "LSQ writeback event"; +} + +template<class Impl> +SimpleIEW<Impl>::SimpleIEW(Params ¶ms) : // Just make this time buffer really big for now issueToExecQueue(5, 5), instQueue(params), @@ -36,11 +64,13 @@ SimpleIEW<Impl, IQ>::SimpleIEW(Params ¶ms) // Instruction queue needs the queue between issue and execute. instQueue.setIssueToExecuteQueue(&issueToExecQueue); + + ldstQueue.setIEW(this); } -template <class Impl, class IQ> +template <class Impl> void -SimpleIEW<Impl, IQ>::regStats() +SimpleIEW<Impl>::regStats() { instQueue.regStats(); @@ -111,9 +141,9 @@ SimpleIEW<Impl, IQ>::regStats() .desc("Number of branches that were predicted taken incorrectly"); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr) +SimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr) { DPRINTF(IEW, "IEW: Setting CPU pointer.\n"); cpu = cpu_ptr; @@ -122,9 +152,9 @@ SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr) ldstQueue.setCPU(cpu_ptr); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) +SimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) { DPRINTF(IEW, "IEW: Setting time buffer pointer.\n"); timeBuffer = tb_ptr; @@ -139,9 +169,9 @@ SimpleIEW<Impl, IQ>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) instQueue.setTimeBuffer(tb_ptr); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) +SimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) { DPRINTF(IEW, "IEW: Setting rename queue pointer.\n"); renameQueue = rq_ptr; @@ -150,9 +180,9 @@ SimpleIEW<Impl, IQ>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) fromRename = renameQueue->getWire(-renameToIEWDelay); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) +SimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) { DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n"); iewQueue = iq_ptr; @@ -161,24 +191,70 @@ SimpleIEW<Impl, IQ>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) toCommit = iewQueue->getWire(0); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::setRenameMap(RenameMap *rm_ptr) +SimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr) { DPRINTF(IEW, "IEW: Setting rename map pointer.\n"); renameMap = rm_ptr; } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::wakeDependents(DynInstPtr &inst) +SimpleIEW<Impl>::squash() { - instQueue.wakeDependents(inst); + DPRINTF(IEW, "IEW: Squashing all instructions.\n"); + _status = Squashing; + + // Tell the IQ to start squashing. + instQueue.squash(); + + // Tell the LDSTQ to start squashing. + ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); +} + +template<class Impl> +void +SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) +{ + DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", + inst->PC); + // Perhaps leave the squashing up to the ROB stage to tell it when to + // squash? + _status = Squashing; + + // Tell rename to squash through the time buffer. + toCommit->squash = true; + // Also send PC update information back to prior stages. + toCommit->squashedSeqNum = inst->seqNum; + toCommit->mispredPC = inst->readPC(); + toCommit->nextPC = inst->readNextPC(); + toCommit->branchMispredict = true; + // Prediction was incorrect, so send back inverse. + toCommit->branchTaken = inst->readNextPC() != + (inst->readPC() + sizeof(MachInst)); +} + +template<class Impl> +void +SimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst) +{ + DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", + inst->PC); + // Perhaps leave the squashing up to the ROB stage to tell it when to + // squash? + _status = Squashing; + + // Tell rename to squash through the time buffer. + toCommit->squash = true; + // Also send PC update information back to prior stages. + toCommit->squashedSeqNum = inst->seqNum; + toCommit->nextPC = inst->readNextPC(); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::block() +SimpleIEW<Impl>::block() { DPRINTF(IEW, "IEW: Blocking.\n"); // Set the status to Blocked. @@ -193,9 +269,9 @@ SimpleIEW<Impl, IQ>::block() // the previous stages are expected to check all possible stall signals. } -template<class Impl, class IQ> +template<class Impl> inline void -SimpleIEW<Impl, IQ>::unblock() +SimpleIEW<Impl>::unblock() { // Check if there's information in the skid buffer. If there is, then // set status to unblocking, otherwise set it directly to running. @@ -215,62 +291,24 @@ SimpleIEW<Impl, IQ>::unblock() } } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::squash() +SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst) { - DPRINTF(IEW, "IEW: Squashing all instructions.\n"); - _status = Squashing; - - // Tell the IQ to start squashing. - instQueue.squash(); - - // Tell the LDSTQ to start squashing. - ldstQueue.squash(fromCommit->commitInfo.doneSeqNum); + instQueue.wakeDependents(inst); } -template<class Impl, class IQ> -void -SimpleIEW<Impl, IQ>::squashDueToBranch(DynInstPtr &inst) -{ - DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", - inst->PC); - // Perhaps leave the squashing up to the ROB stage to tell it when to - // squash? - _status = Squashing; - - // Tell rename to squash through the time buffer. - toCommit->squash = true; - // Also send PC update information back to prior stages. - toCommit->squashedSeqNum = inst->seqNum; - toCommit->mispredPC = inst->readPC(); - toCommit->nextPC = inst->readNextPC(); - toCommit->branchMispredict = true; - // Prediction was incorrect, so send back inverse. - toCommit->branchTaken = inst->readNextPC() != - (inst->readPC() + sizeof(MachInst)); -} -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::squashDueToMem(DynInstPtr &inst) +SimpleIEW<Impl>::instToCommit(DynInstPtr &inst) { - DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n", - inst->PC); - // Perhaps leave the squashing up to the ROB stage to tell it when to - // squash? - _status = Squashing; - // Tell rename to squash through the time buffer. - toCommit->squash = true; - // Also send PC update information back to prior stages. - toCommit->squashedSeqNum = inst->seqNum; - toCommit->nextPC = inst->readNextPC(); } -template <class Impl, class IQ> +template <class Impl> void -SimpleIEW<Impl, IQ>::dispatchInsts() +SimpleIEW<Impl>::dispatchInsts() { //////////////////////////////////////// // DISPATCH/ISSUE stage @@ -329,14 +367,14 @@ SimpleIEW<Impl, IQ>::dispatchInsts() // a signal to this stage to issue and execute that // store. Change to be a bit that says the instruction // has extra work to do at commit. - inst->setCanCommit(); +// inst->setCanCommit(); - instQueue.insertNonSpec(inst); +// instQueue.insertNonSpec(inst); ++iewDispStoreInsts; - ++iewDispNonSpecInsts; +// ++iewDispNonSpecInsts; - continue; +// continue; } else if (inst->isNonSpeculative()) { DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction " "encountered, skipping.\n"); @@ -385,9 +423,9 @@ SimpleIEW<Impl, IQ>::dispatchInsts() } } -template <class Impl, class IQ> +template <class Impl> void -SimpleIEW<Impl, IQ>::executeInsts() +SimpleIEW<Impl>::executeInsts() { //////////////////////////////////////// //EXECUTE/WRITEBACK stage @@ -403,6 +441,8 @@ SimpleIEW<Impl, IQ>::executeInsts() int fu_usage = 0; bool fetch_redirect = false; + int inst_slot = 0; + int time_slot = 0; // Execute/writeback any instructions that are available. for (int inst_num = 0; @@ -452,7 +492,7 @@ SimpleIEW<Impl, IQ>::executeInsts() ++iewExecLoadInsts; } else if (inst->isStore()) { - ldstQueue.executeStore(); + ldstQueue.executeStore(inst); ++iewExecStoreInsts; } else { @@ -473,9 +513,23 @@ SimpleIEW<Impl, IQ>::executeInsts() // For now naively assume that all instructions take one cycle. // Otherwise would have to look into the time buffer based on the // latency of the instruction. + (*iewQueue)[time_slot].insts[inst_slot]; + while ((*iewQueue)[time_slot].insts[inst_slot]) { + if (inst_slot < issueWidth) { + ++inst_slot; + } else { + ++time_slot; + inst_slot = 0; + } + + assert(time_slot < 5); + } + + // May actually have to work this out, especially with loads and stores // Add finished instruction to queue to commit. - toCommit->insts[inst_num] = inst; + (*iewQueue)[time_slot].insts[inst_slot] = inst; + (*iewQueue)[time_slot].size++; // Check if branch was correct. This check happens after the // instruction is added to the queue because even if the branch @@ -518,9 +572,9 @@ SimpleIEW<Impl, IQ>::executeInsts() } } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::tick() +SimpleIEW<Impl>::tick() { // Considering putting all the state-determining stuff in this section. @@ -594,14 +648,20 @@ SimpleIEW<Impl, IQ>::tick() // Write back number of free IQ entries here. toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries(); + ldstQueue.writebackStores(); + // Check the committed load/store signals to see if there's a load // or store to commit. Also check if it's being told to execute a // nonspeculative instruction. - if (fromCommit->commitInfo.commitIsStore) { + // This is pretty inefficient... +// if (0/*fromCommit->commitInfo.commitIsStore*/) { + if (!fromCommit->commitInfo.squash && + !fromCommit->commitInfo.robSquashing) { ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum); - } else if (fromCommit->commitInfo.commitIsLoad) { +// } else if (fromCommit->commitInfo.commitIsLoad) { ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum); } +// } if (fromCommit->commitInfo.nonSpecSeqNum != 0) { instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum); @@ -611,9 +671,9 @@ SimpleIEW<Impl, IQ>::tick() instQueue.numFreeEntries()); } -template<class Impl, class IQ> +template<class Impl> void -SimpleIEW<Impl, IQ>::iew() +SimpleIEW<Impl>::iew() { // Might want to put all state checks in the tick() function. // Check if being told to stall from commit. @@ -663,3 +723,12 @@ SimpleIEW<Impl, IQ>::iew() // Not the best place for it, but this works (hopefully). issueToExecQueue.advance(); } + +#ifndef FULL_SYSTEM +template<class Impl> +void +SimpleIEW<Impl>::lsqWriteback() +{ + ldstQueue.writebackAllInsts(); +} +#endif |