gem5 v24.0.0.0
Loading...
Searching...
No Matches
decode.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "cpu/minor/decode.hh"
39
40#include "base/logging.hh"
41#include "base/trace.hh"
42#include "cpu/minor/pipeline.hh"
43#include "debug/Decode.hh"
44
45namespace gem5
46{
47
48namespace minor
49{
50
51Decode::Decode(const std::string &name,
52 MinorCPU &cpu_,
53 const BaseMinorCPUParams &params,
56 std::vector<InputBuffer<ForwardInstData>> &next_stage_input_buffer) :
57 Named(name),
58 cpu(cpu_),
59 inp(inp_),
60 out(out_),
61 nextStageReserve(next_stage_input_buffer),
62 outputWidth(params.executeInputWidth),
63 processMoreThanOneInput(params.decodeCycleInput),
64 decodeInfo(params.numThreads),
65 threadPriority(0)
66{
67 if (outputWidth < 1)
68 fatal("%s: executeInputWidth must be >= 1 (%d)\n", name, outputWidth);
69
70 if (params.decodeInputBufferSize < 1) {
71 fatal("%s: decodeInputBufferSize must be >= 1 (%d)\n", name,
72 params.decodeInputBufferSize);
73 }
74
75 /* Per-thread input buffers */
76 for (ThreadID tid = 0; tid < params.numThreads; tid++) {
77 inputBuffer.push_back(
79 name + ".inputBuffer" + std::to_string(tid), "insts",
80 params.decodeInputBufferSize));
81 }
82}
83
84const ForwardInstData *
86{
87 /* Get insts from the inputBuffer to work with */
88 if (!inputBuffer[tid].empty()) {
89 const ForwardInstData &head = inputBuffer[tid].front();
90
91 return (head.isBubble() ? NULL : &(inputBuffer[tid].front()));
92 } else {
93 return NULL;
94 }
95}
96
97void
99{
100 if (!inputBuffer[tid].empty())
101 inputBuffer[tid].pop();
102
103 decodeInfo[tid].inputIndex = 0;
104 decodeInfo[tid].inMacroop = false;
105}
106
107#if TRACING_ON
111static void
112dynInstAddTracing(MinorDynInstPtr inst, StaticInstPtr static_inst,
113 MinorCPU &cpu)
114{
115 inst->traceData = cpu.getTracer()->getInstRecord(curTick(),
116 cpu.getContext(inst->id.threadId),
117 inst->staticInst, *inst->pc, static_inst);
118
119 /* Use the execSeqNum as the fetch sequence number as this most closely
120 * matches the other processor models' idea of fetch sequence */
121 if (inst->traceData)
122 inst->traceData->setFetchSeq(inst->id.execSeqNum);
123}
124#endif
125
126void
128{
129 /* Push input onto appropriate input buffer */
130 if (!inp.outputWire->isBubble())
131 inputBuffer[inp.outputWire->threadId].setTail(*inp.outputWire);
132
133 ForwardInstData &insts_out = *out.inputWire;
134
135 assert(insts_out.isBubble());
136
137 for (ThreadID tid = 0; tid < cpu.numThreads; tid++)
138 decodeInfo[tid].blocked = !nextStageReserve[tid].canReserve();
139
141
142 if (tid != InvalidThreadID) {
143 DecodeThreadInfo &decode_info = decodeInfo[tid];
144 const ForwardInstData *insts_in = getInput(tid);
145
146 unsigned int output_index = 0;
147
148 /* Pack instructions into the output while we can. This may involve
149 * using more than one input line */
150 while (insts_in &&
151 decode_info.inputIndex < insts_in->width() && /* Still more input */
152 output_index < outputWidth /* Still more output to fill */)
153 {
154 MinorDynInstPtr inst = insts_in->insts[decode_info.inputIndex];
155
156 if (inst->isBubble()) {
157 /* Skip */
158 decode_info.inputIndex++;
159 decode_info.inMacroop = false;
160 } else {
161 StaticInstPtr static_inst = inst->staticInst;
162 /* Static inst of a macro-op above the output_inst */
163 StaticInstPtr parent_static_inst = NULL;
164 MinorDynInstPtr output_inst = inst;
165
166 if (inst->isFault()) {
167 DPRINTF(Decode, "Fault being passed: %d\n",
168 inst->fault->name());
169
170 decode_info.inputIndex++;
171 decode_info.inMacroop = false;
172 } else if (static_inst->isMacroop()) {
173 /* Generate a new micro-op */
174 StaticInstPtr static_micro_inst;
175
176 /* Set up PC for the next micro-op emitted */
177 if (!decode_info.inMacroop) {
178 set(decode_info.microopPC, *inst->pc);
179 decode_info.inMacroop = true;
180 }
181
182 /* Get the micro-op static instruction from the
183 * static_inst. */
184 static_micro_inst =
185 static_inst->fetchMicroop(
186 decode_info.microopPC->microPC());
187
188 output_inst =
189 new MinorDynInst(static_micro_inst, inst->id);
190 set(output_inst->pc, decode_info.microopPC);
191 output_inst->fault = NoFault;
192
193 /* Allow a predicted next address only on the last
194 * microop */
195 if (static_micro_inst->isLastMicroop()) {
196 output_inst->predictedTaken = inst->predictedTaken;
197 set(output_inst->predictedTarget,
198 inst->predictedTarget);
199 }
200
201 DPRINTF(Decode, "Microop decomposition inputIndex:"
202 " %d output_index: %d lastMicroop: %s microopPC:"
203 " %s inst: %d\n",
204 decode_info.inputIndex, output_index,
205 (static_micro_inst->isLastMicroop() ?
206 "true" : "false"),
207 *decode_info.microopPC,
208 *output_inst);
209
210 /* Acknowledge that the static_inst isn't mine, it's my
211 * parent macro-op's */
212 parent_static_inst = static_inst;
213
214 static_micro_inst->advancePC(*decode_info.microopPC);
215
216 /* Step input if this is the last micro-op */
217 if (static_micro_inst->isLastMicroop()) {
218 decode_info.inputIndex++;
219 decode_info.inMacroop = false;
220 }
221 } else {
222 /* Doesn't need decomposing, pass on instruction */
223 DPRINTF(Decode, "Passing on inst: %s inputIndex:"
224 " %d output_index: %d\n",
225 *output_inst, decode_info.inputIndex, output_index);
226
227 parent_static_inst = static_inst;
228
229 /* Step input */
230 decode_info.inputIndex++;
231 decode_info.inMacroop = false;
232 }
233
234 /* Set execSeqNum of output_inst */
235 output_inst->id.execSeqNum = decode_info.execSeqNum;
236 /* Add tracing */
237#if TRACING_ON
238 dynInstAddTracing(output_inst, parent_static_inst, cpu);
239#endif
240
241 /* Step to next sequence number */
242 decode_info.execSeqNum++;
243
244 /* Correctly size the output before writing */
245 if (output_index == 0) insts_out.resize(outputWidth);
246 /* Push into output */
247 insts_out.insts[output_index] = output_inst;
248 output_index++;
249 }
250
251 /* Have we finished with the input? */
252 if (decode_info.inputIndex == insts_in->width()) {
253 /* If we have just been producing micro-ops, we *must* have
254 * got to the end of that for inputIndex to be pushed past
255 * insts_in->width() */
256 assert(!decode_info.inMacroop);
257 popInput(tid);
258 insts_in = NULL;
259
261 DPRINTF(Decode, "Wrapping\n");
262 insts_in = getInput(tid);
263 }
264 }
265 }
266
267 /* The rest of the output (if any) should already have been packed
268 * with bubble instructions by insts_out's initialisation
269 *
270 * for (; output_index < outputWidth; output_index++)
271 * assert(insts_out.insts[output_index]->isBubble());
272 */
273 }
274
275 /* If we generated output, reserve space for the result in the next stage
276 * and mark the stage as being active this cycle */
277 if (!insts_out.isBubble()) {
278 /* Note activity of following buffer */
280 insts_out.threadId = tid;
281 nextStageReserve[tid].reserve();
282 }
283
284 /* If we still have input to process and somewhere to put it,
285 * mark stage as active */
286 for (ThreadID i = 0; i < cpu.numThreads; i++)
287 {
288 if (getInput(i) && nextStageReserve[i].canReserve()) {
290 break;
291 }
292 }
293
294 /* Make sure the input (if any left) is pushed */
295 if (!inp.outputWire->isBubble())
296 inputBuffer[inp.outputWire->threadId].pushTail();
297}
298
299inline ThreadID
301{
302 /* Select thread via policy. */
303 std::vector<ThreadID> priority_list;
304
305 switch (cpu.threadPolicy) {
306 case enums::SingleThreaded:
307 priority_list.push_back(0);
308 break;
309 case enums::RoundRobin:
310 priority_list = cpu.roundRobinPriority(threadPriority);
311 break;
312 case enums::Random:
313 priority_list = cpu.randomPriority();
314 break;
315 default:
316 panic("Unknown fetch policy");
317 }
318
319 for (auto tid : priority_list) {
320 if (getInput(tid) && !decodeInfo[tid].blocked) {
321 threadPriority = tid;
322 return tid;
323 }
324 }
325
326 return InvalidThreadID;
327}
328
329bool
331{
332 for (const auto &buffer : inputBuffer) {
333 if (!buffer.empty())
334 return false;
335 }
336
337 return (*inp.outputWire).isBubble();
338}
339
340void
342{
343 std::ostringstream data;
344
345 if (decodeInfo[0].blocked)
346 data << 'B';
347 else
348 (*out.inputWire).reportData(data);
349
350 minor::minorTrace("insts=%s\n", data.str());
351 inputBuffer[0].minorTrace();
352}
353
354} // namespace minor
355} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
void activity()
Records that there is activity this cycle.
Definition activity.cc:55
void activateStage(const int idx)
Marks a stage as active.
Definition activity.cc:91
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition base.hh:288
trace::InstTracer * getTracer()
Provide access to the tracer pointer.
Definition base.hh:272
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition base.hh:390
MinorCPU is an in-order CPU model with four fixed pipeline stages:
Definition cpu.hh:85
minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
Definition cpu.hh:95
std::vector< ThreadID > randomPriority()
Definition cpu.hh:181
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
Definition cpu.hh:172
enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
Definition cpu.hh:119
Interface for things with names.
Definition named.hh:39
virtual std::string name() const
Definition named.hh:47
virtual StaticInstPtr fetchMicroop(MicroPC upc) const
Return the microop that goes with a particular micropc.
virtual void advancePC(PCStateBase &pc_state) const =0
bool isMacroop() const
bool isLastMicroop() const
void evaluate()
Pass on input/buffer data to the output if you can.
Definition decode.cc:127
void minorTrace() const
Definition decode.cc:341
bool isDrained()
Is this stage drained? For Decoed, draining is initiated by Execute halting Fetch1 causing Fetch2 to ...
Definition decode.cc:330
std::vector< InputBuffer< ForwardInstData > > inputBuffer
Definition decode.hh:89
const ForwardInstData * getInput(ThreadID tid)
Get a piece of data to work on, or 0 if there is no data.
Definition decode.cc:85
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
Definition decode.cc:98
std::vector< InputBuffer< ForwardInstData > > & nextStageReserve
Interface to reserve space in the next stage.
Definition decode.hh:78
Latch< ForwardInstData >::Output inp
Input port carrying macro instructions from Fetch2.
Definition decode.hh:73
std::vector< DecodeThreadInfo > decodeInfo
Definition decode.hh:127
unsigned int outputWidth
Width of output of this stage/input of next in instructions.
Definition decode.hh:81
Decode(const std::string &name, MinorCPU &cpu_, const BaseMinorCPUParams &params, Latch< ForwardInstData >::Output inp_, Latch< ForwardInstData >::Input out_, std::vector< InputBuffer< ForwardInstData > > &next_stage_input_buffer)
Definition decode.cc:51
Latch< ForwardInstData >::Input out
Output port carrying micro-op decomposed instructions to Execute.
Definition decode.hh:75
ThreadID getScheduledThread()
Use the current threading policy to determine the next thread to decode from.
Definition decode.cc:300
ThreadID threadPriority
Definition decode.hh:128
MinorCPU & cpu
Pointer back to the containing CPU.
Definition decode.hh:70
bool processMoreThanOneInput
If true, more than one input word can be processed each cycle if there is room in the output to conta...
Definition decode.hh:85
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
Definition pipe_data.hh:284
ThreadID threadId
Thread associated with these instructions.
Definition pipe_data.hh:293
void resize(unsigned int width)
Resize a bubble/empty ForwardInstData and fill with bubbles.
Definition pipe_data.cc:263
bool isBubble() const
BubbleIF interface.
Definition pipe_data.cc:250
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
Definition pipe_data.hh:287
unsigned int width() const
Number of instructions carried by this object.
Definition pipe_data.hh:303
Like a Queue but with a restricted interface and a setTail function which, when the queue is empty,...
Definition buffers.hh:572
ThreadID threadId
The thread to which this line/instruction belongs.
Definition dyn_inst.hh:88
InstSeqNum execSeqNum
'Execute' sequence number.
Definition dyn_inst.hh:110
Encapsulate wires on either input or output of the latch.
Definition buffers.hh:252
Dynamic instruction for Minor.
Definition dyn_inst.hh:163
trace::InstRecord * traceData
Trace information for this instruction's execution.
Definition dyn_inst.hh:175
std::unique_ptr< PCStateBase > pc
The fetch address of this instruction.
Definition dyn_inst.hh:178
const StaticInstPtr staticInst
Definition dyn_inst.hh:170
void setFetchSeq(InstSeqNum seq)
virtual InstRecord * getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, const PCStateBase &pc, const StaticInstPtr macroStaticInst=nullptr)=0
STL vector class.
Definition stl.hh:37
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
Decode collects macro-ops from Fetch2 and splits them into micro-ops passed to Execute.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
void minorTrace(const char *fmt, Args ...args)
DPRINTFN for MinorTrace reporting.
Definition trace.hh:66
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
const ThreadID InvalidThreadID
Definition types.hh:236
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
constexpr decltype(nullptr) NoFault
Definition types.hh:253
Minor contains all the definitions within the MinorCPU apart from the CPU class itself.
The constructed pipeline.
Data members after this line are cycle-to-cycle state.
Definition decode.hh:95
InstSeqNum execSeqNum
Source of execSeqNums to number instructions.
Definition decode.hh:121
bool inMacroop
True when we're in the process of decomposing a micro-op and microopPC will be valid.
Definition decode.hh:117
std::unique_ptr< PCStateBase > microopPC
Definition decode.hh:118
unsigned int inputIndex
Index into the inputBuffer's head marking the start of unhandled instructions.
Definition decode.hh:110
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:01 for gem5 by doxygen 1.11.0