1 #include "cpu/beta_cpu/decode.hh"
4 SimpleDecode<Impl>::SimpleDecode(Params ¶ms)
5 : renameToDecodeDelay(params.renameToDecodeDelay),
6 iewToDecodeDelay(params.iewToDecodeDelay),
7 commitToDecodeDelay(params.commitToDecodeDelay),
8 fetchToDecodeDelay(params.fetchToDecodeDelay),
9 decodeWidth(params.decodeWidth),
12 DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth);
18 SimpleDecode<Impl>::regStats()
21 .name(name() + ".decodeIdleCycles")
22 .desc("Number of cycles decode is idle")
23 .prereq(decodeIdleCycles);
25 .name(name() + ".decodeBlockedCycles")
26 .desc("Number of cycles decode is blocked")
27 .prereq(decodeBlockedCycles);
29 .name(name() + ".decodeUnblockCycles")
30 .desc("Number of cycles decode is unblocking")
31 .prereq(decodeUnblockCycles);
33 .name(name() + ".decodeSquashCycles")
34 .desc("Number of cycles decode is squashing")
35 .prereq(decodeSquashCycles);
37 .name(name() + ".decodeBranchMispred")
38 .desc("Number of times decode detected a branch misprediction")
39 .prereq(decodeBranchMispred);
41 .name(name() + ".decodeControlMispred")
42 .desc("Number of times decode detected an instruction incorrectly"
43 " predicted as a control")
44 .prereq(decodeControlMispred);
46 .name(name() + ".decodeDecodedInsts")
47 .desc("Number of instructions handled by decode")
48 .prereq(decodeDecodedInsts);
50 .name(name() + ".decodeSquashedInsts")
51 .desc("Number of squashed instructions handled by decode")
52 .prereq(decodeSquashedInsts);
57 SimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr)
59 DPRINTF(Decode, "Decode: Setting CPU pointer.\n");
65 SimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
67 DPRINTF(Decode, "Decode: Setting time buffer pointer.\n");
70 // Setup wire to write information back to fetch.
71 toFetch = timeBuffer->getWire(0);
73 // Create wires to get information from proper places in time buffer.
74 fromRename = timeBuffer->getWire(-renameToDecodeDelay);
75 fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
76 fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
81 SimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
83 DPRINTF(Decode, "Decode: Setting decode queue pointer.\n");
86 // Setup wire to write information to proper place in decode queue.
87 toRename = decodeQueue->getWire(0);
92 SimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
94 DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n");
97 // Setup wire to read information from fetch queue.
98 fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
103 SimpleDecode<Impl>::block()
105 DPRINTF(Decode, "Decode: Blocking.\n");
107 // Set the status to Blocked.
110 // Add the current inputs to the skid buffer so they can be
111 // reprocessed when this stage unblocks.
112 skidBuffer.push(*fromFetch);
114 // Note that this stage only signals previous stages to stall when
115 // it is the cause of the stall originates at this stage. Otherwise
116 // the previous stages are expected to check all possible stall signals.
121 SimpleDecode<Impl>::unblock()
123 DPRINTF(Decode, "Decode: Unblocking, going to remove "
124 "instructions from skid buffer.\n");
125 // Remove the now processed instructions from the skid buffer.
128 // If there's still information in the skid buffer, then
129 // continue to tell previous stages to stall. They will be
130 // able to restart once the skid buffer is empty.
131 if (!skidBuffer.empty()) {
132 toFetch->decodeInfo.stall = true;
134 DPRINTF(Decode, "Decode: Finished unblocking.\n");
139 // This squash is specifically for when Decode detects a PC-relative branch
140 // was predicted incorrectly.
143 SimpleDecode<Impl>::squash(DynInstPtr &inst)
145 DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction "
146 "detected at decode.\n");
147 Addr new_PC = inst->readNextPC();
149 toFetch->decodeInfo.branchMispredict = true;
150 toFetch->decodeInfo.doneSeqNum = inst->seqNum;
151 toFetch->decodeInfo.predIncorrect = true;
152 toFetch->decodeInfo.squash = true;
153 toFetch->decodeInfo.nextPC = new_PC;
154 toFetch->decodeInfo.branchTaken = true;
156 // Set status to squashing.
159 // Maybe advance the time buffer? Not sure what to do in the normal
162 // Clear the skid buffer in case it has any data in it.
163 while (!skidBuffer.empty())
171 SimpleDecode<Impl>::squash()
173 DPRINTF(Decode, "Decode: Squashing.\n");
174 // Set status to squashing.
177 // Maybe advance the time buffer? Not sure what to do in the normal
180 // Clear the skid buffer in case it has any data in it.
181 while (!skidBuffer.empty())
189 SimpleDecode<Impl>::tick()
191 // Decode should try to execute as many instructions as its bandwidth
192 // will allow, as long as it is not currently blocked.
193 if (_status != Blocked && _status != Squashing) {
194 DPRINTF(Decode, "Decode: Not blocked, so attempting to run "
196 // Make sure that the skid buffer has something in it if the
197 // status is unblocking.
198 assert(_status == Unblocking ? !skidBuffer.empty() : 1);
202 // If the status was unblocking, then instructions from the skid
203 // buffer were used. Remove those instructions and handle
204 // the rest of unblocking.
205 if (_status == Unblocking) {
206 ++decodeUnblockCycles;
208 if (fromFetch->size > 0) {
209 // Add the current inputs to the skid buffer so they can be
210 // reprocessed when this stage unblocks.
211 skidBuffer.push(*fromFetch);
216 } else if (_status == Blocked) {
217 ++decodeBlockedCycles;
219 if (fromFetch->size > 0) {
223 if (!fromRename->renameInfo.stall &&
224 !fromIEW->iewInfo.stall &&
225 !fromCommit->commitInfo.stall) {
226 DPRINTF(Decode, "Decode: Stall signals cleared, going to "
228 _status = Unblocking;
230 // Continue to tell previous stage to block until this
231 // stage is done unblocking.
232 toFetch->decodeInfo.stall = true;
234 DPRINTF(Decode, "Decode: Still blocked.\n");
235 toFetch->decodeInfo.stall = true;
238 if (fromCommit->commitInfo.squash ||
239 fromCommit->commitInfo.robSquashing) {
242 } else if (_status == Squashing) {
243 ++decodeSquashCycles;
245 if (!fromCommit->commitInfo.squash &&
246 !fromCommit->commitInfo.robSquashing) {
248 } else if (fromCommit->commitInfo.squash) {
256 SimpleDecode<Impl>::decode()
258 // Check time buffer if being told to squash.
259 if (fromCommit->commitInfo.squash) {
264 // Check time buffer if being told to stall.
265 if (fromRename->renameInfo.stall ||
266 fromIEW->iewInfo.stall ||
267 fromCommit->commitInfo.stall)
273 // Check fetch queue to see if instructions are available.
274 // If no available instructions, do nothing, unless this stage is
275 // currently unblocking.
276 if (fromFetch->size == 0 && _status != Unblocking) {
277 DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n");
278 // Should I change the status to idle?
283 // Might be better to use a base DynInst * instead?
286 unsigned to_rename_index = 0;
288 int insts_available = _status == Unblocking ?
289 skidBuffer.front().size :
294 if (insts_available) {
295 DPRINTF(Decode, "Decode: Instructions available.\n");
297 if (_status == Unblocking && skidBuffer.empty()) {
298 DPRINTF(Decode, "Decode: No instructions available, skid buffer "
300 } else if (_status != Unblocking &&
301 !fromFetch->insts[0]) {
302 DPRINTF(Decode, "Decode: No instructions available, fetch queue "
305 panic("Decode: No instructions available, unexpected condition!"
311 while (insts_available > 0)
313 DPRINTF(Decode, "Decode: Sending instruction to rename.\n");
315 inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
316 fromFetch->insts[numInst];
318 DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n",
319 inst->seqNum, inst->readPC());
321 if (inst->isSquashed()) {
322 DPRINTF(Decode, "Decode: Instruction %i with PC %#x is "
323 "squashed, skipping.\n",
324 inst->seqNum, inst->readPC());
326 ++decodeSquashedInsts;
334 // This current instruction is valid, so add it into the decode
335 // queue. The next instruction may not be valid, so check to
336 // see if branches were predicted correctly.
337 toRename->insts[to_rename_index] = inst;
341 // Ensure that if it was predicted as a branch, it really is a
343 if (inst->predTaken() && !inst->isControl()) {
344 panic("Instruction predicted as a branch!");
346 ++decodeControlMispred;
347 // Might want to set some sort of boolean and just do
348 // a check at the end
353 // Go ahead and compute any PC-relative branches.
355 if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
357 inst->setNextPC(inst->branchTarget());
359 if (inst->mispredicted()) {
360 ++decodeBranchMispred;
361 // Might want to set some sort of boolean and just do
362 // a check at the end
368 // Normally can check if a direct branch has the right target
369 // addr (either the immediate, or the branch PC + 4) and redirect
370 // fetch if it's incorrect.
373 // Also check if instructions have no source registers. Mark
374 // them as ready to issue at any time. Not sure if this check
375 // should exist here or at a later stage; however it doesn't matter
376 // too much for function correctness.
377 // Isn't this handled by the inst queue?
378 if (inst->numSrcRegs() == 0) {
382 // Increment which instruction we're looking at.
385 ++decodeDecodedInsts;