gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
45 namespace gem5
46 {
47 
48 namespace minor
49 {
50 
51 Decode::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 
84 const 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 
97 void
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
108 
111 static void
112 dynInstAddTracing(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 
126 void
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 
299 inline 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 
329 bool
331 {
332  for (const auto &buffer : inputBuffer) {
333  if (!buffer.empty())
334  return false;
335  }
336 
337  return (*inp.outputWire).isBubble();
338 }
339 
340 void
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
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:200
gem5::MinorCPU::randomPriority
std::vector< ThreadID > randomPriority()
Definition: cpu.hh:181
gem5::NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:253
gem5::minor::Decode::nextStageReserve
std::vector< InputBuffer< ForwardInstData > > & nextStageReserve
Interface to reserve space in the next stage.
Definition: decode.hh:78
gem5::minor::Decode::minorTrace
void minorTrace() const
Definition: decode.cc:341
gem5::minor::ForwardInstData::isBubble
bool isBubble() const
BubbleIF interface.
Definition: pipe_data.cc:250
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::minor::ForwardInstData::insts
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
Definition: pipe_data.hh:287
gem5::minor::ForwardInstData::threadId
ThreadID threadId
Thread associated with these instructions.
Definition: pipe_data.hh:293
gem5::auxv::Random
@ Random
Definition: aux_vector.hh:87
gem5::minor::Decode::outputWidth
unsigned int outputWidth
Width of output of this stage/input of next in instructions.
Definition: decode.hh:81
gem5::minor::MinorDynInst::traceData
trace::InstRecord * traceData
Trace information for this instruction's execution.
Definition: dyn_inst.hh:175
gem5::minor::MinorDynInst::staticInst
const StaticInstPtr staticInst
Definition: dyn_inst.hh:170
gem5::ArmISA::set
Bitfield< 12, 11 > set
Definition: misc_types.hh:760
gem5::trace::InstTracer::getInstRecord
virtual InstRecord * getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, const PCStateBase &pc, const StaticInstPtr macroStaticInst=nullptr)=0
gem5::minor::Decode::DecodeThreadInfo::microopPC
std::unique_ptr< PCStateBase > microopPC
Definition: decode.hh:118
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::minor::Decode::isDrained
bool isDrained()
Is this stage drained? For Decoed, draining is initiated by Execute halting Fetch1 causing Fetch2 to ...
Definition: decode.cc:330
minor
gem5::MinorCPU
MinorCPU is an in-order CPU model with four fixed pipeline stages:
Definition: cpu.hh:84
std::vector
STL vector class.
Definition: stl.hh:37
gem5::minor::ForwardInstData
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
Definition: pipe_data.hh:283
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::StaticInst::advancePC
virtual void advancePC(PCStateBase &pc_state) const =0
gem5::RefCountingPtr< MinorDynInst >
gem5::StaticInst::fetchMicroop
virtual StaticInstPtr fetchMicroop(MicroPC upc) const
Return the microop that goes with a particular micropc.
Definition: static_inst.cc:39
gem5::minor::InputBuffer
Like a Queue but with a restricted interface and a setTail function which, when the queue is empty,...
Definition: buffers.hh:571
gem5::Named
Interface for things with names.
Definition: named.hh:38
gem5::minor::Decode::popInput
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
Definition: decode.cc:98
gem5::BaseCPU::numThreads
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition: base.hh:384
gem5::minor::Decode::decodeInfo
std::vector< DecodeThreadInfo > decodeInfo
Definition: decode.hh:127
gem5::minor::Latch::Output
Definition: buffers.hh:262
decode.hh
gem5::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:117
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::minor::Latch::Input
Encapsulate wires on either input or output of the latch.
Definition: buffers.hh:251
pipeline.hh
gem5::minor::Decode::DecodeThreadInfo::inputIndex
unsigned int inputIndex
Index into the inputBuffer's head marking the start of unhandled instructions.
Definition: decode.hh:110
gem5::minor::ForwardInstData::width
unsigned int width() const
Number of instructions carried by this object.
Definition: pipe_data.hh:303
gem5::InvalidThreadID
const ThreadID InvalidThreadID
Definition: types.hh:236
gem5::BaseCPU::getContext
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition: base.hh:288
gem5::minor::Decode::evaluate
void evaluate()
Pass on input/buffer data to the output if you can.
Definition: decode.cc:127
name
const std::string & name()
Definition: trace.cc:48
gem5::StaticInst::isLastMicroop
bool isLastMicroop() const
Definition: static_inst.hh:188
gem5::minor::minorTrace
void minorTrace(const char *fmt, Args ...args)
DPRINTFN for MinorTrace reporting.
Definition: trace.hh:66
gem5::ActivityRecorder::activity
void activity()
Records that there is activity this cycle.
Definition: activity.cc:55
gem5::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:85
gem5::minor::Decode::cpu
MinorCPU & cpu
Pointer back to the containing CPU.
Definition: decode.hh:70
gem5::ActivityRecorder::activateStage
void activateStage(const int idx)
Marks a stage as active.
Definition: activity.cc:91
gem5::minor::ForwardInstData::resize
void resize(unsigned int width)
Resize a bubble/empty ForwardInstData and fill with bubbles.
Definition: pipe_data.cc:263
gem5::minor::MinorDynInst::id
InstId id
Definition: dyn_inst.hh:172
gem5::minor::MinorDynInst::pc
std::unique_ptr< PCStateBase > pc
The fetch address of this instruction.
Definition: dyn_inst.hh:178
gem5::minor::MinorDynInst
Dynamic instruction for Minor.
Definition: dyn_inst.hh:162
gem5::minor::Decode::threadPriority
ThreadID threadPriority
Definition: decode.hh:128
gem5::minor::Decode::DecodeThreadInfo::execSeqNum
InstSeqNum execSeqNum
Source of execSeqNums to number instructions.
Definition: decode.hh:121
gem5::StaticInst::isMacroop
bool isMacroop() const
Definition: static_inst.hh:185
gem5::minor::Decode::getScheduledThread
ThreadID getScheduledThread()
Use the current threading policy to determine the next thread to decode from.
Definition: decode.cc:300
gem5::minor::Decode::out
Latch< ForwardInstData >::Input out
Output port carrying micro-op decomposed instructions to Execute.
Definition: decode.hh:75
logging.hh
gem5::minor::InstId::execSeqNum
InstSeqNum execSeqNum
'Execute' sequence number.
Definition: dyn_inst.hh:110
gem5::BaseCPU::getTracer
trace::InstTracer * getTracer()
Provide access to the tracer pointer.
Definition: base.hh:272
gem5::MinorCPU::threadPolicy
enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
Definition: cpu.hh:119
trace.hh
gem5::minor::Pipeline::DecodeStageId
@ DecodeStageId
Definition: pipeline.hh:103
gem5::MinorCPU::activityRecorder
minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
Definition: cpu.hh:95
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::minor::Decode::Decode
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
gem5::trace::InstRecord::setFetchSeq
void setFetchSeq(InstSeqNum seq)
Definition: insttracer.hh:245
gem5::minor::Decode::DecodeThreadInfo
Data members after this line are cycle-to-cycle state.
Definition: decode.hh:94
gem5::MinorCPU::roundRobinPriority
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
Definition: cpu.hh:172
gem5::ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:235
gem5::minor::Decode
Definition: decode.hh:66
gem5::minor::Decode::inputBuffer
std::vector< InputBuffer< ForwardInstData > > inputBuffer
Definition: decode.hh:89
gem5::minor::InstId::threadId
ThreadID threadId
The thread to which this line/instruction belongs.
Definition: dyn_inst.hh:88
gem5::minor::Decode::inp
Latch< ForwardInstData >::Output inp
Input port carrying macro instructions from Fetch2.
Definition: decode.hh:73
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::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:85

Generated on Sun Jul 30 2023 01:56:52 for gem5 by doxygen 1.8.17