gem5  v20.1.0.0
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 "cpu/minor/pipeline.hh"
41 #include "debug/Decode.hh"
42 
43 namespace Minor
44 {
45 
46 Decode::Decode(const std::string &name,
47  MinorCPU &cpu_,
48  MinorCPUParams &params,
51  std::vector<InputBuffer<ForwardInstData>> &next_stage_input_buffer) :
52  Named(name),
53  cpu(cpu_),
54  inp(inp_),
55  out(out_),
56  nextStageReserve(next_stage_input_buffer),
57  outputWidth(params.executeInputWidth),
58  processMoreThanOneInput(params.decodeCycleInput),
59  decodeInfo(params.numThreads),
60  threadPriority(0)
61 {
62  if (outputWidth < 1)
63  fatal("%s: executeInputWidth must be >= 1 (%d)\n", name, outputWidth);
64 
65  if (params.decodeInputBufferSize < 1) {
66  fatal("%s: decodeInputBufferSize must be >= 1 (%d)\n", name,
67  params.decodeInputBufferSize);
68  }
69 
70  /* Per-thread input buffers */
71  for (ThreadID tid = 0; tid < params.numThreads; tid++) {
72  inputBuffer.push_back(
74  name + ".inputBuffer" + std::to_string(tid), "insts",
75  params.decodeInputBufferSize));
76  }
77 }
78 
79 const ForwardInstData *
81 {
82  /* Get insts from the inputBuffer to work with */
83  if (!inputBuffer[tid].empty()) {
84  const ForwardInstData &head = inputBuffer[tid].front();
85 
86  return (head.isBubble() ? NULL : &(inputBuffer[tid].front()));
87  } else {
88  return NULL;
89  }
90 }
91 
92 void
94 {
95  if (!inputBuffer[tid].empty())
96  inputBuffer[tid].pop();
97 
98  decodeInfo[tid].inputIndex = 0;
99  decodeInfo[tid].inMacroop = false;
100 }
101 
102 #if TRACING_ON
103 
106 static void
107 dynInstAddTracing(MinorDynInstPtr inst, StaticInstPtr static_inst,
108  MinorCPU &cpu)
109 {
110  inst->traceData = cpu.getTracer()->getInstRecord(curTick(),
111  cpu.getContext(inst->id.threadId),
112  inst->staticInst, inst->pc, static_inst);
113 
114  /* Use the execSeqNum as the fetch sequence number as this most closely
115  * matches the other processor models' idea of fetch sequence */
116  if (inst->traceData)
117  inst->traceData->setFetchSeq(inst->id.execSeqNum);
118 }
119 #endif
120 
121 void
123 {
124  /* Push input onto appropriate input buffer */
125  if (!inp.outputWire->isBubble())
126  inputBuffer[inp.outputWire->threadId].setTail(*inp.outputWire);
127 
128  ForwardInstData &insts_out = *out.inputWire;
129 
130  assert(insts_out.isBubble());
131 
132  for (ThreadID tid = 0; tid < cpu.numThreads; tid++)
133  decodeInfo[tid].blocked = !nextStageReserve[tid].canReserve();
134 
136 
137  if (tid != InvalidThreadID) {
138  DecodeThreadInfo &decode_info = decodeInfo[tid];
139  const ForwardInstData *insts_in = getInput(tid);
140 
141  unsigned int output_index = 0;
142 
143  /* Pack instructions into the output while we can. This may involve
144  * using more than one input line */
145  while (insts_in &&
146  decode_info.inputIndex < insts_in->width() && /* Still more input */
147  output_index < outputWidth /* Still more output to fill */)
148  {
149  MinorDynInstPtr inst = insts_in->insts[decode_info.inputIndex];
150 
151  if (inst->isBubble()) {
152  /* Skip */
153  decode_info.inputIndex++;
154  decode_info.inMacroop = false;
155  } else {
156  StaticInstPtr static_inst = inst->staticInst;
157  /* Static inst of a macro-op above the output_inst */
158  StaticInstPtr parent_static_inst = NULL;
159  MinorDynInstPtr output_inst = inst;
160 
161  if (inst->isFault()) {
162  DPRINTF(Decode, "Fault being passed: %d\n",
163  inst->fault->name());
164 
165  decode_info.inputIndex++;
166  decode_info.inMacroop = false;
167  } else if (static_inst->isMacroop()) {
168  /* Generate a new micro-op */
169  StaticInstPtr static_micro_inst;
170 
171  /* Set up PC for the next micro-op emitted */
172  if (!decode_info.inMacroop) {
173  decode_info.microopPC = inst->pc;
174  decode_info.inMacroop = true;
175  }
176 
177  /* Get the micro-op static instruction from the
178  * static_inst. */
179  static_micro_inst =
180  static_inst->fetchMicroop(
181  decode_info.microopPC.microPC());
182 
183  output_inst = new MinorDynInst(inst->id);
184  output_inst->pc = decode_info.microopPC;
185  output_inst->staticInst = static_micro_inst;
186  output_inst->fault = NoFault;
187 
188  /* Allow a predicted next address only on the last
189  * microop */
190  if (static_micro_inst->isLastMicroop()) {
191  output_inst->predictedTaken = inst->predictedTaken;
192  output_inst->predictedTarget = inst->predictedTarget;
193  }
194 
195  DPRINTF(Decode, "Microop decomposition inputIndex:"
196  " %d output_index: %d lastMicroop: %s microopPC:"
197  " %d.%d inst: %d\n",
198  decode_info.inputIndex, output_index,
199  (static_micro_inst->isLastMicroop() ?
200  "true" : "false"),
201  decode_info.microopPC.instAddr(),
202  decode_info.microopPC.microPC(),
203  *output_inst);
204 
205  /* Acknowledge that the static_inst isn't mine, it's my
206  * parent macro-op's */
207  parent_static_inst = static_inst;
208 
209  static_micro_inst->advancePC(decode_info.microopPC);
210 
211  /* Step input if this is the last micro-op */
212  if (static_micro_inst->isLastMicroop()) {
213  decode_info.inputIndex++;
214  decode_info.inMacroop = false;
215  }
216  } else {
217  /* Doesn't need decomposing, pass on instruction */
218  DPRINTF(Decode, "Passing on inst: %s inputIndex:"
219  " %d output_index: %d\n",
220  *output_inst, decode_info.inputIndex, output_index);
221 
222  parent_static_inst = static_inst;
223 
224  /* Step input */
225  decode_info.inputIndex++;
226  decode_info.inMacroop = false;
227  }
228 
229  /* Set execSeqNum of output_inst */
230  output_inst->id.execSeqNum = decode_info.execSeqNum;
231  /* Add tracing */
232 #if TRACING_ON
233  dynInstAddTracing(output_inst, parent_static_inst, cpu);
234 #endif
235 
236  /* Step to next sequence number */
237  decode_info.execSeqNum++;
238 
239  /* Correctly size the output before writing */
240  if (output_index == 0) insts_out.resize(outputWidth);
241  /* Push into output */
242  insts_out.insts[output_index] = output_inst;
243  output_index++;
244  }
245 
246  /* Have we finished with the input? */
247  if (decode_info.inputIndex == insts_in->width()) {
248  /* If we have just been producing micro-ops, we *must* have
249  * got to the end of that for inputIndex to be pushed past
250  * insts_in->width() */
251  assert(!decode_info.inMacroop);
252  popInput(tid);
253  insts_in = NULL;
254 
256  DPRINTF(Decode, "Wrapping\n");
257  insts_in = getInput(tid);
258  }
259  }
260  }
261 
262  /* The rest of the output (if any) should already have been packed
263  * with bubble instructions by insts_out's initialisation
264  *
265  * for (; output_index < outputWidth; output_index++)
266  * assert(insts_out.insts[output_index]->isBubble());
267  */
268  }
269 
270  /* If we generated output, reserve space for the result in the next stage
271  * and mark the stage as being active this cycle */
272  if (!insts_out.isBubble()) {
273  /* Note activity of following buffer */
275  insts_out.threadId = tid;
276  nextStageReserve[tid].reserve();
277  }
278 
279  /* If we still have input to process and somewhere to put it,
280  * mark stage as active */
281  for (ThreadID i = 0; i < cpu.numThreads; i++)
282  {
283  if (getInput(i) && nextStageReserve[i].canReserve()) {
285  break;
286  }
287  }
288 
289  /* Make sure the input (if any left) is pushed */
290  if (!inp.outputWire->isBubble())
291  inputBuffer[inp.outputWire->threadId].pushTail();
292 }
293 
294 inline ThreadID
296 {
297  /* Select thread via policy. */
298  std::vector<ThreadID> priority_list;
299 
300  switch (cpu.threadPolicy) {
301  case Enums::SingleThreaded:
302  priority_list.push_back(0);
303  break;
304  case Enums::RoundRobin:
305  priority_list = cpu.roundRobinPriority(threadPriority);
306  break;
307  case Enums::Random:
308  priority_list = cpu.randomPriority();
309  break;
310  default:
311  panic("Unknown fetch policy");
312  }
313 
314  for (auto tid : priority_list) {
315  if (getInput(tid) && !decodeInfo[tid].blocked) {
316  threadPriority = tid;
317  return tid;
318  }
319  }
320 
321  return InvalidThreadID;
322 }
323 
324 bool
326 {
327  for (const auto &buffer : inputBuffer) {
328  if (!buffer.empty())
329  return false;
330  }
331 
332  return (*inp.outputWire).isBubble();
333 }
334 
335 void
337 {
338  std::ostringstream data;
339 
340  if (decodeInfo[0].blocked)
341  data << 'B';
342  else
343  (*out.inputWire).reportData(data);
344 
345  MINORTRACE("insts=%s\n", data.str());
346  inputBuffer[0].minorTrace();
347 }
348 
349 }
InvalidThreadID
const ThreadID InvalidThreadID
Definition: types.hh:228
Minor::Decode::DecodeThreadInfo::inMacroop
bool inMacroop
True when we're in the process of decomposing a micro-op and microopPC will be valid.
Definition: decode.hh:115
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
Minor::ForwardInstData::threadId
ThreadID threadId
Thread associated with these instructions.
Definition: pipe_data.hh:263
Minor::ForwardInstData
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
Definition: pipe_data.hh:253
Minor::Decode::inp
Latch< ForwardInstData >::Output inp
Input port carrying macro instructions from Fetch2.
Definition: decode.hh:67
data
const char data[]
Definition: circlebuf.test.cc:42
Minor::Decode::DecodeThreadInfo::inputIndex
unsigned int inputIndex
Index into the inputBuffer's head marking the start of unhandled instructions.
Definition: decode.hh:108
StaticInst::advancePC
virtual void advancePC(TheISA::PCState &pcState) const =0
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:227
Minor::Latch::Input
Encapsulate wires on either input or output of the latch.
Definition: buffers.hh:245
Minor::Decode::DecodeThreadInfo::execSeqNum
InstSeqNum execSeqNum
Source of execSeqNums to number instructions.
Definition: decode.hh:119
Trace::InstRecord::setFetchSeq
void setFetchSeq(InstSeqNum seq)
Definition: insttracer.hh:220
Minor::Decode::evaluate
void evaluate()
Pass on input/buffer data to the output if you can.
Definition: decode.cc:122
MinorCPU::activityRecorder
Minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
Definition: cpu.hh:88
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
Minor::InstId::execSeqNum
InstSeqNum execSeqNum
'Execute' sequence number.
Definition: dyn_inst.hh:103
MinorCPU::threadPolicy
Enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
Definition: cpu.hh:112
MINORTRACE
#define MINORTRACE(...)
DPRINTFN for MinorTrace reporting.
Definition: trace.hh:60
std::vector
STL vector class.
Definition: stl.hh:37
BaseCPU::getContext
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition: base.hh:283
Minor::Decode::outputWidth
unsigned int outputWidth
Width of output of this stage/input of next in instructions.
Definition: decode.hh:75
Minor
Definition: activity.cc:44
Minor::Decode::DecodeThreadInfo
Data members after this line are cycle-to-cycle state.
Definition: decode.hh:88
Trace::InstTracer::getInstRecord
virtual InstRecord * getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, TheISA::PCState pc, const StaticInstPtr macroStaticInst=NULL)=0
Minor::Decode::out
Latch< ForwardInstData >::Input out
Output port carrying micro-op decomposed instructions to Execute.
Definition: decode.hh:69
decode.hh
Minor::Decode
Definition: decode.hh:60
Minor::Decode::popInput
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
Definition: decode.cc:93
Minor::Decode::minorTrace
void minorTrace() const
Definition: decode.cc:336
Minor::Decode::Decode
Decode(const std::string &name, MinorCPU &cpu_, MinorCPUParams &params, Latch< ForwardInstData >::Output inp_, Latch< ForwardInstData >::Input out_, std::vector< InputBuffer< ForwardInstData >> &next_stage_input_buffer)
Definition: decode.cc:46
Minor::MinorDynInst
Dynamic instruction for Minor.
Definition: dyn_inst.hh:155
MinorCPU
MinorCPU is an in-order CPU model with four fixed pipeline stages:
Definition: cpu.hh:77
Minor::Latch::Output
Definition: buffers.hh:256
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
Minor::ForwardInstData::width
unsigned int width() const
Number of instructions carried by this object.
Definition: pipe_data.hh:273
Minor::MinorDynInst::traceData
Trace::InstRecord * traceData
Trace information for this instruction's execution.
Definition: dyn_inst.hh:168
StaticInst::isMacroop
bool isMacroop() const
Definition: static_inst.hh:198
Minor::ForwardInstData::isBubble
bool isBubble() const
BubbleIF interface.
Definition: pipe_data.cc:247
pipeline.hh
Minor::Decode::processMoreThanOneInput
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:79
Minor::Pipeline::DecodeStageId
@ DecodeStageId
Definition: pipeline.hh:100
Minor::Decode::isDrained
bool isDrained()
Is this stage drained? For Decoed, draining is initiated by Execute halting Fetch1 causing Fetch2 to ...
Definition: decode.cc:325
Minor::ForwardInstData::insts
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
Definition: pipe_data.hh:257
Minor::Decode::DecodeThreadInfo::microopPC
TheISA::PCState microopPC
Definition: decode.hh:116
Minor::InputBuffer
Like a Queue but with a restricted interface and a setTail function which, when the queue is empty,...
Definition: buffers.hh:565
Minor::Decode::nextStageReserve
std::vector< InputBuffer< ForwardInstData > > & nextStageReserve
Interface to reserve space in the next stage.
Definition: decode.hh:72
Minor::MinorDynInst::id
InstId id
Definition: dyn_inst.hh:165
Minor::InstId::threadId
ThreadID threadId
The thread to which this line/instruction belongs.
Definition: dyn_inst.hh:81
Minor::Decode::cpu
MinorCPU & cpu
Pointer back to the containing CPU.
Definition: decode.hh:64
NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:245
name
const std::string & name()
Definition: trace.cc:50
Minor::Decode::threadPriority
ThreadID threadPriority
Definition: decode.hh:126
Named
Definition: trace.hh:147
StaticInst::isLastMicroop
bool isLastMicroop() const
Definition: static_inst.hh:201
Minor::Decode::getInput
const ForwardInstData * getInput(ThreadID tid)
Get a piece of data to work on, or 0 if there is no data.
Definition: decode.cc:80
StaticInst::fetchMicroop
virtual StaticInstPtr fetchMicroop(MicroPC upc) const
Return the microop that goes with a particular micropc.
Definition: static_inst.cc:98
ActivityRecorder::activity
void activity()
Records that there is activity this cycle.
Definition: activity.cc:54
MinorCPU::roundRobinPriority
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
Definition: cpu.hh:165
BaseCPU::getTracer
Trace::InstTracer * getTracer()
Provide access to the tracer pointer.
Definition: base.hh:267
BaseCPU::numThreads
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition: base.hh:363
Minor::Decode::getScheduledThread
ThreadID getScheduledThread()
Use the current threading policy to determine the next thread to decode from.
Definition: decode.cc:295
Minor::MinorDynInst::pc
TheISA::PCState pc
The fetch address of this instruction.
Definition: dyn_inst.hh:171
Minor::Decode::inputBuffer
std::vector< InputBuffer< ForwardInstData > > inputBuffer
Definition: decode.hh:83
ActivityRecorder::activateStage
void activateStage(const int idx)
Marks a stage as active.
Definition: activity.cc:90
MinorCPU::randomPriority
std::vector< ThreadID > randomPriority()
Definition: cpu.hh:174
RefCountingPtr< MinorDynInst >
Minor::ForwardInstData::resize
void resize(unsigned int width)
Resize a bubble/empty ForwardInstData and fill with bubbles.
Definition: pipe_data.cc:260
Named::name
const std::string & name() const
Definition: trace.hh:156
Minor::MinorDynInst::staticInst
StaticInstPtr staticInst
Definition: dyn_inst.hh:163
Minor::Decode::decodeInfo
std::vector< DecodeThreadInfo > decodeInfo
Definition: decode.hh:125
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:08 for gem5 by doxygen 1.8.17