Some stuff aparently didn't get committed which was from before the new repository...
[gem5.git] / cpu / base_dyn_inst.hh
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #ifndef __CPU_BASE_DYN_INST_HH__
30 #define __CPU_BASE_DYN_INST_HH__
31
32 #include <string>
33 #include <vector>
34
35 #include "base/fast_alloc.hh"
36 #include "base/trace.hh"
37 #include "config/full_system.hh"
38 #include "cpu/exetrace.hh"
39 #include "cpu/inst_seq.hh"
40 #include "cpu/o3/comm.hh"
41 #include "cpu/static_inst.hh"
42 #include "encumbered/cpu/full/bpred_update.hh"
43 #include "encumbered/cpu/full/op_class.hh"
44 #include "encumbered/cpu/full/spec_memory.hh"
45 #include "encumbered/cpu/full/spec_state.hh"
46 #include "encumbered/mem/functional/main.hh"
47
48 /**
49 * @file
50 * Defines a dynamic instruction context.
51 */
52
53 // Forward declaration.
54 template <class ISA>
55 class StaticInstPtr;
56
57 template <class Impl>
58 class BaseDynInst : public FastAlloc, public RefCounted
59 {
60 public:
61 // Typedef for the CPU.
62 typedef typename Impl::FullCPU FullCPU;
63
64 //Typedef to get the ISA.
65 typedef typename Impl::ISA ISA;
66
67 /// Binary machine instruction type.
68 typedef typename ISA::MachInst MachInst;
69 /// Memory address type.
70 typedef typename ISA::Addr Addr;
71 /// Logical register index type.
72 typedef typename ISA::RegIndex RegIndex;
73 /// Integer register index type.
74 typedef typename ISA::IntReg IntReg;
75
76 enum {
77 MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
78 MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
79 };
80
81 /** The static inst used by this dyn inst. */
82 StaticInstPtr<ISA> staticInst;
83
84 ////////////////////////////////////////////
85 //
86 // INSTRUCTION EXECUTION
87 //
88 ////////////////////////////////////////////
89 Trace::InstRecord *traceData;
90
91 template <class T>
92 Fault read(Addr addr, T &data, unsigned flags);
93
94 template <class T>
95 Fault write(T data, Addr addr, unsigned flags,
96 uint64_t *res);
97
98 void prefetch(Addr addr, unsigned flags);
99 void writeHint(Addr addr, int size, unsigned flags);
100 Fault copySrcTranslate(Addr src);
101 Fault copy(Addr dest);
102
103 /** @todo: Consider making this private. */
104 public:
105 /** Is this instruction valid. */
106 bool valid;
107
108 /** The sequence number of the instruction. */
109 InstSeqNum seqNum;
110
111 /** How many source registers are ready. */
112 unsigned readyRegs;
113
114 /** Is the instruction completed. */
115 bool completed;
116
117 /** Can this instruction issue. */
118 bool canIssue;
119
120 /** Has this instruction issued. */
121 bool issued;
122
123 /** Has this instruction executed (or made it through execute) yet. */
124 bool executed;
125
126 /** Can this instruction commit. */
127 bool canCommit;
128
129 /** Is this instruction squashed. */
130 bool squashed;
131
132 /** Is this instruction squashed in the instruction queue. */
133 bool squashedInIQ;
134
135 /** Is this a recover instruction. */
136 bool recoverInst;
137
138 /** Is this a thread blocking instruction. */
139 bool blockingInst; /* this inst has called thread_block() */
140
141 /** Is this a thread syncrhonization instruction. */
142 bool threadsyncWait;
143
144 /** The thread this instruction is from. */
145 short threadNumber;
146
147 /** data address space ID, for loads & stores. */
148 short asid;
149
150 /** Pointer to the FullCPU object. */
151 FullCPU *cpu;
152
153 /** Pointer to the exec context. Will not exist in the final version. */
154 ExecContext *xc;
155
156 /** The kind of fault this instruction has generated. */
157 Fault fault;
158
159 /** The effective virtual address (lds & stores only). */
160 Addr effAddr;
161
162 /** The effective physical address. */
163 Addr physEffAddr;
164
165 /** Effective virtual address for a copy source. */
166 Addr copySrcEffAddr;
167
168 /** Effective physical address for a copy source. */
169 Addr copySrcPhysEffAddr;
170
171 /** The memory request flags (from translation). */
172 unsigned memReqFlags;
173
174 /** The size of the data to be stored. */
175 int storeSize;
176
177 /** The data to be stored. */
178 IntReg storeData;
179
180 union Result {
181 uint64_t integer;
182 float fp;
183 double dbl;
184 };
185
186 /** The result of the instruction; assumes for now that there's only one
187 * destination register.
188 */
189 Result instResult;
190
191 /** PC of this instruction. */
192 Addr PC;
193
194 /** Next non-speculative PC. It is not filled in at fetch, but rather
195 * once the target of the branch is truly known (either decode or
196 * execute).
197 */
198 Addr nextPC;
199
200 /** Predicted next PC. */
201 Addr predPC;
202
203 /** Count of total number of dynamic instructions. */
204 static int instcount;
205
206 /** Whether or not the source register is ready. Not sure this should be
207 * here vs. the derived class.
208 */
209 bool _readySrcRegIdx[MaxInstSrcRegs];
210
211 public:
212 /** BaseDynInst constructor given a binary instruction. */
213 BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
214 FullCPU *cpu);
215
216 /** BaseDynInst constructor given a static inst pointer. */
217 BaseDynInst(StaticInstPtr<ISA> &_staticInst);
218
219 /** BaseDynInst destructor. */
220 ~BaseDynInst();
221
222 private:
223 /** Function to initialize variables in the constructors. */
224 void initVars();
225
226 public:
227 void
228 trace_mem(Fault fault, // last fault
229 MemCmd cmd, // last command
230 Addr addr, // virtual address of access
231 void *p, // memory accessed
232 int nbytes); // access size
233
234 /** Dumps out contents of this BaseDynInst. */
235 void dump();
236
237 /** Dumps out contents of this BaseDynInst into given string. */
238 void dump(std::string &outstring);
239
240 /** Returns the fault type. */
241 Fault getFault() { return fault; }
242
243 /** Checks whether or not this instruction has had its branch target
244 * calculated yet. For now it is not utilized and is hacked to be
245 * always false.
246 */
247 bool doneTargCalc() { return false; }
248
249 /** Returns the next PC. This could be the speculative next PC if it is
250 * called prior to the actual branch target being calculated.
251 */
252 Addr readNextPC() { return nextPC; }
253
254 /** Set the predicted target of this current instruction. */
255 void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
256
257 /** Returns the predicted target of the branch. */
258 Addr readPredTarg() { return predPC; }
259
260 /** Returns whether the instruction was predicted taken or not. */
261 bool predTaken() {
262 return( predPC != (PC + sizeof(MachInst) ) );
263 }
264
265 /** Returns whether the instruction mispredicted. */
266 bool mispredicted() { return (predPC != nextPC); }
267
268 //
269 // Instruction types. Forward checks to StaticInst object.
270 //
271 bool isNop() const { return staticInst->isNop(); }
272 bool isMemRef() const { return staticInst->isMemRef(); }
273 bool isLoad() const { return staticInst->isLoad(); }
274 bool isStore() const { return staticInst->isStore(); }
275 bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
276 bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
277 bool isCopy() const { return staticInst->isCopy(); }
278 bool isInteger() const { return staticInst->isInteger(); }
279 bool isFloating() const { return staticInst->isFloating(); }
280 bool isControl() const { return staticInst->isControl(); }
281 bool isCall() const { return staticInst->isCall(); }
282 bool isReturn() const { return staticInst->isReturn(); }
283 bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
284 bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
285 bool isCondCtrl() const { return staticInst->isCondCtrl(); }
286 bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
287 bool isThreadSync() const { return staticInst->isThreadSync(); }
288 bool isSerializing() const { return staticInst->isSerializing(); }
289 bool isMemBarrier() const { return staticInst->isMemBarrier(); }
290 bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
291 bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
292
293 /** Returns the opclass of this instruction. */
294 OpClass opClass() const { return staticInst->opClass(); }
295
296 /** Returns the branch target address. */
297 Addr branchTarget() const { return staticInst->branchTarget(PC); }
298
299 /** Number of source registers. */
300 int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
301
302 /** Number of destination registers. */
303 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
304
305 // the following are used to track physical register usage
306 // for machines with separate int & FP reg files
307 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
308 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
309
310 /** Returns the logical register index of the i'th destination register. */
311 RegIndex destRegIdx(int i) const
312 {
313 return staticInst->destRegIdx(i);
314 }
315
316 /** Returns the logical register index of the i'th source register. */
317 RegIndex srcRegIdx(int i) const
318 {
319 return staticInst->srcRegIdx(i);
320 }
321
322 /** Returns the result of an integer instruction. */
323 uint64_t readIntResult() { return instResult.integer; }
324
325 /** Returns the result of a floating point instruction. */
326 float readFloatResult() { return instResult.fp; }
327
328 /** Returns the result of a floating point (double) instruction. */
329 double readDoubleResult() { return instResult.dbl; }
330
331 //Push to .cc file.
332 /** Records that one of the source registers is ready. */
333 void markSrcRegReady()
334 {
335 ++readyRegs;
336 if(readyRegs == numSrcRegs()) {
337 canIssue = true;
338 }
339 }
340
341 /** Marks a specific register as ready.
342 * @todo: Move this to .cc file.
343 */
344 void markSrcRegReady(RegIndex src_idx)
345 {
346 ++readyRegs;
347
348 _readySrcRegIdx[src_idx] = 1;
349
350 if(readyRegs == numSrcRegs()) {
351 canIssue = true;
352 }
353 }
354
355 /** Returns if a source register is ready. */
356 bool isReadySrcRegIdx(int idx) const
357 {
358 return this->_readySrcRegIdx[idx];
359 }
360
361 /** Sets this instruction as completed. */
362 void setCompleted() { completed = true; }
363
364 /** Returns whethe or not this instruction is completed. */
365 bool isCompleted() const { return completed; }
366
367 /** Sets this instruction as ready to issue. */
368 void setCanIssue() { canIssue = true; }
369
370 /** Returns whether or not this instruction is ready to issue. */
371 bool readyToIssue() const { return canIssue; }
372
373 /** Sets this instruction as issued from the IQ. */
374 void setIssued() { issued = true; }
375
376 /** Returns whether or not this instruction has issued. */
377 bool isIssued() const { return issued; }
378
379 /** Sets this instruction as executed. */
380 void setExecuted() { executed = true; }
381
382 /** Returns whether or not this instruction has executed. */
383 bool isExecuted() const { return executed; }
384
385 /** Sets this instruction as ready to commit. */
386 void setCanCommit() { canCommit = true; }
387
388 /** Clears this instruction as being ready to commit. */
389 void clearCanCommit() { canCommit = false; }
390
391 /** Returns whether or not this instruction is ready to commit. */
392 bool readyToCommit() const { return canCommit; }
393
394 /** Sets this instruction as squashed. */
395 void setSquashed() { squashed = true; }
396
397 /** Returns whether or not this instruction is squashed. */
398 bool isSquashed() const { return squashed; }
399
400 /** Sets this instruction as squashed in the IQ. */
401 void setSquashedInIQ() { squashedInIQ = true; }
402
403 /** Returns whether or not this instruction is squashed in the IQ. */
404 bool isSquashedInIQ() const { return squashedInIQ; }
405
406 /** Read the PC of this instruction. */
407 const Addr readPC() const { return PC; }
408
409 /** Set the next PC of this instruction (its actual target). */
410 void setNextPC(uint64_t val) { nextPC = val; }
411
412 /** Returns the exec context.
413 * @todo: Remove this once the ExecContext is no longer used.
414 */
415 ExecContext *xcBase() { return xc; }
416
417 private:
418 /** Instruction effective address.
419 * @todo: Consider if this is necessary or not.
420 */
421 Addr instEffAddr;
422 /** Whether or not the effective address calculation is completed.
423 * @todo: Consider if this is necessary or not.
424 */
425 bool eaCalcDone;
426
427 public:
428 /** Sets the effective address. */
429 void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
430
431 /** Returns the effective address. */
432 const Addr &getEA() const { return instEffAddr; }
433
434 /** Returns whether or not the eff. addr. calculation has been completed. */
435 bool doneEACalc() { return eaCalcDone; }
436
437 /** Returns whether or not the eff. addr. source registers are ready. */
438 bool eaSrcsReady();
439
440 public:
441 /** Load queue index. */
442 int16_t lqIdx;
443
444 /** Store queue index. */
445 int16_t sqIdx;
446 };
447
448 template<class Impl>
449 template<class T>
450 inline Fault
451 BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
452 {
453 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
454 req->asid = asid;
455
456 fault = cpu->translateDataReadReq(req);
457
458 // Record key MemReq parameters so we can generate another one
459 // just like it for the timing access without calling translate()
460 // again (which might mess up the TLB).
461 // Do I ever really need this? -KTL 3/05
462 effAddr = req->vaddr;
463 physEffAddr = req->paddr;
464 memReqFlags = req->flags;
465
466 /**
467 * @todo
468 * Replace the disjoint functional memory with a unified one and remove
469 * this hack.
470 */
471 #if !FULL_SYSTEM
472 req->paddr = req->vaddr;
473 #endif
474
475 if (fault == No_Fault) {
476 fault = cpu->read(req, data, lqIdx);
477 } else {
478 // Return a fixed value to keep simulation deterministic even
479 // along misspeculated paths.
480 data = (T)-1;
481 }
482
483 if (traceData) {
484 traceData->setAddr(addr);
485 traceData->setData(data);
486 }
487
488 return fault;
489 }
490
491 template<class Impl>
492 template<class T>
493 inline Fault
494 BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
495 {
496 if (traceData) {
497 traceData->setAddr(addr);
498 traceData->setData(data);
499 }
500
501 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
502
503 req->asid = asid;
504
505 fault = cpu->translateDataWriteReq(req);
506
507 // Record key MemReq parameters so we can generate another one
508 // just like it for the timing access without calling translate()
509 // again (which might mess up the TLB).
510 effAddr = req->vaddr;
511 physEffAddr = req->paddr;
512 memReqFlags = req->flags;
513
514 /**
515 * @todo
516 * Replace the disjoint functional memory with a unified one and remove
517 * this hack.
518 */
519 #if !FULL_SYSTEM
520 req->paddr = req->vaddr;
521 #endif
522
523 if (fault == No_Fault) {
524 fault = cpu->write(req, data, sqIdx);
525 }
526
527 if (res) {
528 // always return some result to keep misspeculated paths
529 // (which will ignore faults) deterministic
530 *res = (fault == No_Fault) ? req->result : 0;
531 }
532
533 return fault;
534 }
535
536 #endif // __CPU_BASE_DYN_INST_HH__