1 #ifndef __SIMPLE_DECODE_CC__
2 #define __SIMPLE_DECODE_CC__
4 #include "cpu/beta_cpu/decode.hh"
7 SimpleDecode<Impl>::SimpleDecode(Params ¶ms)
8 : renameToDecodeDelay(params.renameToDecodeDelay),
9 iewToDecodeDelay(params.iewToDecodeDelay),
10 commitToDecodeDelay(params.commitToDecodeDelay),
11 fetchToDecodeDelay(params.fetchToDecodeDelay),
12 decodeWidth(params.decodeWidth),
15 DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth);
21 SimpleDecode<Impl>::regStats()
24 .name(name() + ".decodeIdleCycles")
25 .desc("Number of cycles decode is idle")
26 .prereq(decodeIdleCycles);
28 .name(name() + ".decodeBlockedCycles")
29 .desc("Number of cycles decode is blocked")
30 .prereq(decodeBlockedCycles);
32 .name(name() + ".decodeUnblockCycles")
33 .desc("Number of cycles decode is unblocking")
34 .prereq(decodeUnblockCycles);
36 .name(name() + ".decodeSquashCycles")
37 .desc("Number of cycles decode is squashing")
38 .prereq(decodeSquashCycles);
40 .name(name() + ".decodeBranchMispred")
41 .desc("Number of times decode detected a branch misprediction")
42 .prereq(decodeBranchMispred);
44 .name(name() + ".decodeControlMispred")
45 .desc("Number of times decode detected an instruction incorrectly"
46 " predicted as a control")
47 .prereq(decodeControlMispred);
49 .name(name() + ".decodeDecodedInsts")
50 .desc("Number of instructions handled by decode")
51 .prereq(decodeDecodedInsts);
53 .name(name() + ".decodeSquashedInsts")
54 .desc("Number of squashed instructions handled by decode")
55 .prereq(decodeSquashedInsts);
60 SimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr)
62 DPRINTF(Decode, "Decode: Setting CPU pointer.\n");
68 SimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
70 DPRINTF(Decode, "Decode: Setting time buffer pointer.\n");
73 // Setup wire to write information back to fetch.
74 toFetch = timeBuffer->getWire(0);
76 // Create wires to get information from proper places in time buffer.
77 fromRename = timeBuffer->getWire(-renameToDecodeDelay);
78 fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
79 fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
84 SimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
86 DPRINTF(Decode, "Decode: Setting decode queue pointer.\n");
89 // Setup wire to write information to proper place in decode queue.
90 toRename = decodeQueue->getWire(0);
95 SimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
97 DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n");
100 // Setup wire to read information from fetch queue.
101 fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
106 SimpleDecode<Impl>::block()
108 DPRINTF(Decode, "Decode: Blocking.\n");
110 // Set the status to Blocked.
113 // Add the current inputs to the skid buffer so they can be
114 // reprocessed when this stage unblocks.
115 skidBuffer.push(*fromFetch);
117 // Note that this stage only signals previous stages to stall when
118 // it is the cause of the stall originates at this stage. Otherwise
119 // the previous stages are expected to check all possible stall signals.
124 SimpleDecode<Impl>::unblock()
126 DPRINTF(Decode, "Decode: Unblocking, going to remove "
127 "instructions from skid buffer.\n");
128 // Remove the now processed instructions from the skid buffer.
131 // If there's still information in the skid buffer, then
132 // continue to tell previous stages to stall. They will be
133 // able to restart once the skid buffer is empty.
134 if (!skidBuffer.empty()) {
135 toFetch->decodeInfo.stall = true;
137 DPRINTF(Decode, "Decode: Finished unblocking.\n");
142 // This squash is specifically for when Decode detects a PC-relative branch
143 // was predicted incorrectly.
146 SimpleDecode<Impl>::squash(DynInstPtr &inst)
148 DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction "
149 "detected at decode.\n");
150 Addr new_PC = inst->nextPC;
152 toFetch->decodeInfo.branchMispredict = true;
153 toFetch->decodeInfo.doneSeqNum = inst->seqNum;
154 toFetch->decodeInfo.predIncorrect = true;
155 toFetch->decodeInfo.squash = true;
156 toFetch->decodeInfo.nextPC = new_PC;
157 toFetch->decodeInfo.branchTaken = true;
159 // Set status to squashing.
162 // Maybe advance the time buffer? Not sure what to do in the normal
165 // Clear the skid buffer in case it has any data in it.
166 while (!skidBuffer.empty())
174 SimpleDecode<Impl>::squash()
176 DPRINTF(Decode, "Decode: Squashing.\n");
177 // Set status to squashing.
180 // Maybe advance the time buffer? Not sure what to do in the normal
183 // Clear the skid buffer in case it has any data in it.
184 while (!skidBuffer.empty())
192 SimpleDecode<Impl>::tick()
194 // Decode should try to execute as many instructions as its bandwidth
195 // will allow, as long as it is not currently blocked.
196 if (_status != Blocked && _status != Squashing) {
197 DPRINTF(Decode, "Decode: Not blocked, so attempting to run "
199 // Make sure that the skid buffer has something in it if the
200 // status is unblocking.
201 assert(_status == Unblocking ? !skidBuffer.empty() : 1);
205 // If the status was unblocking, then instructions from the skid
206 // buffer were used. Remove those instructions and handle
207 // the rest of unblocking.
208 if (_status == Unblocking) {
209 ++decodeUnblockCycles;
211 if (fromFetch->size > 0) {
212 // Add the current inputs to the skid buffer so they can be
213 // reprocessed when this stage unblocks.
214 skidBuffer.push(*fromFetch);
219 } else if (_status == Blocked) {
220 ++decodeBlockedCycles;
222 if (fromFetch->size > 0) {
226 if (!fromRename->renameInfo.stall &&
227 !fromIEW->iewInfo.stall &&
228 !fromCommit->commitInfo.stall) {
229 DPRINTF(Decode, "Decode: Stall signals cleared, going to "
231 _status = Unblocking;
233 // Continue to tell previous stage to block until this
234 // stage is done unblocking.
235 toFetch->decodeInfo.stall = true;
237 DPRINTF(Decode, "Decode: Still blocked.\n");
238 toFetch->decodeInfo.stall = true;
241 if (fromCommit->commitInfo.squash ||
242 fromCommit->commitInfo.robSquashing) {
245 } else if (_status == Squashing) {
246 ++decodeSquashCycles;
248 if (!fromCommit->commitInfo.squash &&
249 !fromCommit->commitInfo.robSquashing) {
251 } else if (fromCommit->commitInfo.squash) {
259 SimpleDecode<Impl>::decode()
261 // Check time buffer if being told to squash.
262 if (fromCommit->commitInfo.squash) {
267 // Check time buffer if being told to stall.
268 if (fromRename->renameInfo.stall ||
269 fromIEW->iewInfo.stall ||
270 fromCommit->commitInfo.stall)
276 // Check fetch queue to see if instructions are available.
277 // If no available instructions, do nothing, unless this stage is
278 // currently unblocking.
279 if (fromFetch->size == 0 && _status != Unblocking) {
280 DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n");
281 // Should I change the status to idle?
286 // Might be better to use a base DynInst * instead?
289 unsigned to_rename_index = 0;
291 int insts_available = _status == Unblocking ?
292 skidBuffer.front().size :
297 if (insts_available) {
298 DPRINTF(Decode, "Decode: Instructions available.\n");
300 if (_status == Unblocking && skidBuffer.empty()) {
301 DPRINTF(Decode, "Decode: No instructions available, skid buffer "
303 } else if (_status != Unblocking &&
304 !fromFetch->insts[0]) {
305 DPRINTF(Decode, "Decode: No instructions available, fetch queue "
308 panic("Decode: No instructions available, unexpected condition!"
314 while (insts_available > 0)
316 DPRINTF(Decode, "Decode: Sending instruction to rename.\n");
318 inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
319 fromFetch->insts[numInst];
321 DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n",
322 inst->seqNum, inst->readPC());
324 if (inst->isSquashed()) {
325 DPRINTF(Decode, "Decode: Instruction %i with PC %#x is "
326 "squashed, skipping.\n",
327 inst->seqNum, inst->readPC());
329 ++decodeSquashedInsts;
337 // This current instruction is valid, so add it into the decode
338 // queue. The next instruction may not be valid, so check to
339 // see if branches were predicted correctly.
340 toRename->insts[to_rename_index] = inst;
344 // Ensure that if it was predicted as a branch, it really is a
346 if (inst->predTaken() && !inst->isControl()) {
347 panic("Instruction predicted as a branch!");
349 ++decodeControlMispred;
350 // Might want to set some sort of boolean and just do
351 // a check at the end
356 // Go ahead and compute any PC-relative branches.
358 if (inst->isDirectCtrl() && inst->isUncondCtrl() &&
359 inst->numDestRegs() == 0 && inst->numSrcRegs() == 0) {
363 if (inst->mispredicted()) {
364 ++decodeBranchMispred;
365 // Might want to set some sort of boolean and just do
366 // a check at the end
372 // Normally can check if a direct branch has the right target
373 // addr (either the immediate, or the branch PC + 4) and redirect
374 // fetch if it's incorrect.
377 // Also check if instructions have no source registers. Mark
378 // them as ready to issue at any time. Not sure if this check
379 // should exist here or at a later stage; however it doesn't matter
380 // too much for function correctness.
381 // Isn't this handled by the inst queue?
382 if (inst->numSrcRegs() == 0) {
386 // Increment which instruction we're looking at.
389 ++decodeDecodedInsts;
397 #endif // __SIMPLE_DECODE_CC__