Check in of new CPU. This checkin works under non-Fullsystem mode, with no caches.
[gem5.git] / cpu / base_dyn_inst.hh
1 /*
2 * Copyright (c) 2001-2004 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 __BASE_DYN_INST_HH__
30 #define __BASE_DYN_INST_HH__
31
32 #include <vector>
33 #include <string>
34
35 #include "base/fast_alloc.hh"
36 #include "base/trace.hh"
37
38 #include "cpu/static_inst.hh"
39 #include "cpu/beta_cpu/comm.hh"
40 #include "cpu/full_cpu/bpred_update.hh"
41 #include "mem/functional_mem/main_memory.hh"
42 #include "cpu/full_cpu/spec_memory.hh"
43 #include "cpu/inst_seq.hh"
44 #include "cpu/full_cpu/op_class.hh"
45 #include "cpu/full_cpu/spec_state.hh"
46
47 /**
48 * @file
49 * Defines a dynamic instruction context.
50 */
51
52 namespace Trace {
53 class InstRecord;
54 };
55
56 class BaseInst
57 {
58 };
59
60 template <class Impl>
61 class BaseDynInst : public FastAlloc
62 {
63 public:
64 // Typedef for the CPU.
65 typedef typename Impl::FullCPU FullCPU;
66
67 //Typedef to get the ISA.
68 typedef typename Impl::ISA ISA;
69
70 /// Binary machine instruction type.
71 typedef typename ISA::MachInst MachInst;
72 /// Memory address type.
73 typedef typename ISA::Addr Addr;
74 /// Logical register index type.
75 typedef typename ISA::RegIndex RegIndex;
76 /// Integer register index type.
77 typedef typename ISA::IntReg IntReg;
78
79 enum {
80 MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
81 MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
82 };
83
84 StaticInstPtr<ISA> staticInst;
85
86 ////////////////////////////////////////////
87 //
88 // INSTRUCTION EXECUTION
89 //
90 ////////////////////////////////////////////
91 Trace::InstRecord *traceData;
92
93 // void setCPSeq(InstSeqNum seq);
94
95 template <class T>
96 Fault read(Addr addr, T &data, unsigned flags);
97
98 template <class T>
99 Fault write(T data, Addr addr, unsigned flags,
100 uint64_t *res);
101
102
103 IntReg *getIntegerRegs(void);
104 FunctionalMemory *getMemory(void);
105
106 void prefetch(Addr addr, unsigned flags);
107 void writeHint(Addr addr, int size, unsigned flags);
108 Fault copySrcTranslate(Addr src);
109 Fault copy(Addr dest);
110
111 public:
112 /** Is this instruction valid. */
113 bool valid;
114
115 /** The sequence number of the instruction. */
116 InstSeqNum seqNum;
117
118 /** How many source registers are ready. */
119 unsigned readyRegs;
120
121 /** Can this instruction issue. */
122 bool canIssue;
123
124 /** Has this instruction issued. */
125 bool issued;
126
127 /** Has this instruction executed (or made it through execute) yet. */
128 bool executed;
129
130 /** Can this instruction commit. */
131 bool canCommit;
132
133 /** Is this instruction squashed. */
134 bool squashed;
135
136 /** Is this instruction squashed in the instruction queue. */
137 bool squashedInIQ;
138
139 /** Is this a recover instruction. */
140 bool recoverInst;
141
142 /** Is this a thread blocking instruction. */
143 bool blockingInst; /* this inst has called thread_block() */
144
145 /** Is this a thread syncrhonization instruction. */
146 bool threadsyncWait;
147
148 /** If the BTB missed. */
149 bool btbMissed;
150
151 /** The thread this instruction is from. */
152 short threadNumber;
153
154 /** If instruction is speculative. */
155 short specMode;
156
157 /** data address space ID, for loads & stores. */
158 short asid;
159
160 /** Pointer to the FullCPU object. */
161 FullCPU *cpu;
162
163 /** Pointer to the exec context. Will not exist in the final version. */
164 ExecContext *xc;
165
166 /** The kind of fault this instruction has generated. */
167 Fault fault;
168
169 /** The effective virtual address (lds & stores only). */
170 Addr effAddr;
171
172 /** The effective physical address. */
173 Addr physEffAddr;
174
175 /** Effective virtual address for a copy source. */
176 Addr copySrcEffAddr;
177
178 /** Effective physical address for a copy source. */
179 Addr copySrcPhysEffAddr;
180
181 /** The memory request flags (from translation). */
182 unsigned memReqFlags;
183
184 /** The size of the data to be stored. */
185 int storeSize;
186
187 /** The data to be stored. */
188 IntReg storeData;
189
190 /** Result of this instruction, if an integer. */
191 uint64_t intResult;
192
193 /** Result of this instruction, if a float. */
194 float floatResult;
195
196 /** Result of this instruction, if a double. */
197 double doubleResult;
198
199 /** PC of this instruction. */
200 Addr PC;
201
202 /** Next non-speculative PC. It is not filled in at fetch, but rather
203 * once the target of the branch is truly known (either decode or
204 * execute).
205 */
206 Addr nextPC;
207
208 /** Predicted next PC. */
209 Addr predPC;
210
211 /** Count of total number of dynamic instructions. */
212 static int instcount;
213
214 /** Did this instruction do a spec write? */
215 bool specMemWrite;
216
217 private:
218 /** Physical register index of the destination registers of this
219 * instruction.
220 */
221 PhysRegIndex _destRegIdx[MaxInstDestRegs];
222
223 /** Physical register index of the source registers of this
224 * instruction.
225 */
226 PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
227
228 /** Whether or not the source register is ready. */
229 bool _readySrcRegIdx[MaxInstSrcRegs];
230
231 /** Physical register index of the previous producers of the
232 * architected destinations.
233 */
234 PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
235
236 public:
237 /** BaseDynInst constructor given a binary instruction. */
238 BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
239 FullCPU *cpu);
240
241 /** BaseDynInst constructor given a static inst pointer. */
242 BaseDynInst(StaticInstPtr<ISA> &_staticInst);
243
244 /** BaseDynInst destructor. */
245 ~BaseDynInst();
246
247 #if 0
248 Fault
249 mem_access(MemCmd cmd, // Read or Write access cmd
250 Addr addr, // virtual address of access
251 void *p, // input/output buffer
252 int nbytes); // access size
253 #endif
254
255 void
256 trace_mem(Fault fault, // last fault
257 MemCmd cmd, // last command
258 Addr addr, // virtual address of access
259 void *p, // memory accessed
260 int nbytes); // access size
261
262 /** Dumps out contents of this BaseDynInst. */
263 void dump();
264
265 /** Dumps out contents of this BaseDynInst into given string. */
266 void dump(std::string &outstring);
267
268 /** Returns the fault type. */
269 Fault getFault() { return fault; }
270
271 /** Checks whether or not this instruction has had its branch target
272 * calculated yet. For now it is not utilized and is hacked to be
273 * always false.
274 */
275 bool doneTargCalc() { return false; }
276
277 /** Returns the calculated target of the branch. */
278 Addr readCalcTarg() { return nextPC; }
279
280 Addr readNextPC() { return nextPC; }
281
282 /** Set the predicted target of this current instruction. */
283 void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
284
285 /** Returns the predicted target of the branch. */
286 Addr readPredTarg() { return predPC; }
287
288 /** Returns whether the instruction was predicted taken or not. */
289 bool predTaken() {
290 // DPRINTF(FullCPU, "PC: %08p\n", PC);
291 // DPRINTF(FullCPU, "predPC: %08p\n", predPC);
292
293 return( predPC != (PC + sizeof(MachInst) ) );
294 }
295
296 /** Returns whether the instruction mispredicted. */
297 bool mispredicted() { return (predPC != nextPC); }
298
299 //
300 // Instruction types. Forward checks to StaticInst object.
301 //
302 bool isNop() const { return staticInst->isNop(); }
303 bool isMemRef() const { return staticInst->isMemRef(); }
304 bool isLoad() const { return staticInst->isLoad(); }
305 bool isStore() const { return staticInst->isStore(); }
306 bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
307 bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
308 bool isCopy() const { return staticInst->isCopy(); }
309 bool isInteger() const { return staticInst->isInteger(); }
310 bool isFloating() const { return staticInst->isFloating(); }
311 bool isControl() const { return staticInst->isControl(); }
312 bool isCall() const { return staticInst->isCall(); }
313 bool isReturn() const { return staticInst->isReturn(); }
314 bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
315 bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
316 bool isCondCtrl() const { return staticInst->isCondCtrl(); }
317 bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
318 bool isThreadSync() const { return staticInst->isThreadSync(); }
319 bool isSerializing() const { return staticInst->isSerializing(); }
320 bool isMemBarrier() const { return staticInst->isMemBarrier(); }
321 bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
322 bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
323
324 int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
325 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
326
327 // the following are used to track physical register usage
328 // for machines with separate int & FP reg files
329 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
330 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
331
332 /** Returns the logical register index of the i'th destination register. */
333 RegIndex destRegIdx(int i) const
334 {
335 return staticInst->destRegIdx(i);
336 }
337
338 /** Returns the logical register index of the i'th source register. */
339 RegIndex srcRegIdx(int i) const
340 {
341 return staticInst->srcRegIdx(i);
342 }
343
344 /** Returns the physical register index of the i'th destination
345 * register.
346 */
347 PhysRegIndex renamedDestRegIdx(int idx) const
348 {
349 return _destRegIdx[idx];
350 }
351
352 /** Returns the physical register index of the i'th source register. */
353 PhysRegIndex renamedSrcRegIdx(int idx) const
354 {
355 return _srcRegIdx[idx];
356 }
357
358 bool isReadySrcRegIdx(int idx) const
359 {
360 return _readySrcRegIdx[idx];
361 }
362
363 /** Returns the physical register index of the previous physical register
364 * that remapped to the same logical register index.
365 */
366 PhysRegIndex prevDestRegIdx(int idx) const
367 {
368 return _prevDestRegIdx[idx];
369 }
370
371 /** Renames a destination register to a physical register. Also records
372 * the previous physical register that the logical register mapped to.
373 */
374 void renameDestReg(int idx,
375 PhysRegIndex renamed_dest,
376 PhysRegIndex previous_rename)
377 {
378 _destRegIdx[idx] = renamed_dest;
379 _prevDestRegIdx[idx] = previous_rename;
380 }
381
382 /** Renames a source logical register to the physical register which
383 * has/will produce that logical register's result.
384 * @todo: add in whether or not the source register is ready.
385 */
386 void renameSrcReg(int idx, PhysRegIndex renamed_src)
387 {
388 _srcRegIdx[idx] = renamed_src;
389 }
390
391 //Push to .cc file.
392 /** Records that one of the source registers is ready. */
393 void markSrcRegReady()
394 {
395 ++readyRegs;
396 if(readyRegs == numSrcRegs()) {
397 canIssue = true;
398 }
399 }
400
401 void markSrcRegReady(RegIndex src_idx)
402 {
403 ++readyRegs;
404
405 _readySrcRegIdx[src_idx] = 1;
406
407 if(readyRegs == numSrcRegs()) {
408 canIssue = true;
409 }
410 }
411
412 /** Sets this instruction as ready to issue. */
413 void setCanIssue() { canIssue = true; }
414
415 /** Returns whether or not this instruction is ready to issue. */
416 bool readyToIssue() const { return canIssue; }
417
418 /** Sets this instruction as issued from the IQ. */
419 void setIssued() { issued = true; }
420
421 /** Returns whether or not this instruction has issued. */
422 bool isIssued() { return issued; }
423
424 /** Sets this instruction as executed. */
425 void setExecuted() { executed = true; }
426
427 /** Returns whether or not this instruction has executed. */
428 bool isExecuted() { return executed; }
429
430 /** Sets this instruction as ready to commit. */
431 void setCanCommit() { canCommit = true; }
432
433 /** Returns whether or not this instruction is ready to commit. */
434 bool readyToCommit() const { return canCommit; }
435
436 /** Sets this instruction as squashed. */
437 void setSquashed() { squashed = true; }
438
439 /** Returns whether or not this instruction is squashed. */
440 bool isSquashed() const { return squashed; }
441
442 /** Sets this instruction as squashed in the IQ. */
443 void setSquashedInIQ() { squashedInIQ = true; }
444
445 /** Returns whether or not this instruction is squashed in the IQ. */
446 bool isSquashedInIQ() { return squashedInIQ; }
447
448 /** Returns the opclass of this instruction. */
449 OpClass opClass() const { return staticInst->opClass(); }
450
451 /** Returns whether or not the BTB missed. */
452 bool btbMiss() const { return btbMissed; }
453
454 /** Returns the branch target address. */
455 Addr branchTarget() const { return staticInst->branchTarget(PC); }
456
457 // The register accessor methods provide the index of the
458 // instruction's operand (e.g., 0 or 1), not the architectural
459 // register index, to simplify the implementation of register
460 // renaming. We find the architectural register index by indexing
461 // into the instruction's own operand index table. Note that a
462 // raw pointer to the StaticInst is provided instead of a
463 // ref-counted StaticInstPtr to redice overhead. This is fine as
464 // long as these methods don't copy the pointer into any long-term
465 // storage (which is pretty hard to imagine they would have reason
466 // to do).
467
468 uint64_t readIntReg(StaticInst<ISA> *si, int idx)
469 {
470 return cpu->readIntReg(_srcRegIdx[idx]);
471 }
472
473 float readFloatRegSingle(StaticInst<ISA> *si, int idx)
474 {
475 return cpu->readFloatRegSingle(_srcRegIdx[idx]);
476 }
477
478 double readFloatRegDouble(StaticInst<ISA> *si, int idx)
479 {
480 return cpu->readFloatRegDouble(_srcRegIdx[idx]);
481 }
482
483 uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
484 {
485 return cpu->readFloatRegInt(_srcRegIdx[idx]);
486 }
487 /** @todo: Make results into arrays so they can handle multiple dest
488 * registers.
489 */
490 void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
491 {
492 cpu->setIntReg(_destRegIdx[idx], val);
493 intResult = val;
494 }
495
496 void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
497 {
498 cpu->setFloatRegSingle(_destRegIdx[idx], val);
499 floatResult = val;
500 }
501
502 void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
503 {
504 cpu->setFloatRegDouble(_destRegIdx[idx], val);
505 doubleResult = val;
506 }
507
508 void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
509 {
510 cpu->setFloatRegInt(_destRegIdx[idx], val);
511 intResult = val;
512 }
513
514 /** Read the PC of this instruction. */
515 Addr readPC() { return PC; }
516
517 /** Set the next PC of this instruction (its actual target). */
518 void setNextPC(uint64_t val) { nextPC = val; }
519
520 // bool misspeculating() { return cpu->misspeculating(); }
521 ExecContext *xcBase() { return xc; }
522 };
523
524 template<class Impl>
525 template<class T>
526 inline Fault
527 BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
528 {
529 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
530 req->asid = asid;
531
532 fault = cpu->translateDataReadReq(req);
533
534 // Record key MemReq parameters so we can generate another one
535 // just like it for the timing access without calling translate()
536 // again (which might mess up the TLB).
537 effAddr = req->vaddr;
538 physEffAddr = req->paddr;
539 memReqFlags = req->flags;
540
541 /**
542 * @todo
543 * Replace the disjoint functional memory with a unified one and remove
544 * this hack.
545 */
546 #ifndef FULL_SYSTEM
547 req->paddr = req->vaddr;
548 #endif
549
550 if (fault == No_Fault) {
551 fault = cpu->read(req, data);
552 }
553 else {
554 // Return a fixed value to keep simulation deterministic even
555 // along misspeculated paths.
556 data = (T)-1;
557 }
558
559 if (traceData) {
560 traceData->setAddr(addr);
561 traceData->setData(data);
562 }
563
564 return fault;
565 }
566
567 template<class Impl>
568 template<class T>
569 inline Fault
570 BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
571 {
572 if (traceData) {
573 traceData->setAddr(addr);
574 traceData->setData(data);
575 }
576
577 storeSize = sizeof(T);
578 storeData = data;
579 if (specMode)
580 specMemWrite = true;
581
582 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
583
584 req->asid = asid;
585
586 fault = cpu->translateDataWriteReq(req);
587
588 // Record key MemReq parameters so we can generate another one
589 // just like it for the timing access without calling translate()
590 // again (which might mess up the TLB).
591 effAddr = req->vaddr;
592 physEffAddr = req->paddr;
593 memReqFlags = req->flags;
594
595 /**
596 * @todo
597 * Replace the disjoint functional memory with a unified one and remove
598 * this hack.
599 */
600 #ifndef FULL_SYSTEM
601 req->paddr = req->vaddr;
602 #endif
603
604 if (fault == No_Fault) {
605 fault = cpu->write(req, data);
606 }
607
608 if (res) {
609 // always return some result to keep misspeculated paths
610 // (which will ignore faults) deterministic
611 *res = (fault == No_Fault) ? req->result : 0;
612 }
613
614 return fault;
615 }
616
617 #endif // __DYN_INST_HH__