56b9114d23f402df78a54106147914a306557580
[gem5.git] / src / cpu / base_dyn_inst.hh
1 /*
2 * Copyright (c) 2011, 2013, 2016-2020 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * Copyright (c) 2009 The University of Edinburgh
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 #ifndef __CPU_BASE_DYN_INST_HH__
44 #define __CPU_BASE_DYN_INST_HH__
45
46 #include <array>
47 #include <bitset>
48 #include <deque>
49 #include <list>
50 #include <string>
51
52 #include "arch/generic/tlb.hh"
53 #include "arch/utility.hh"
54 #include "base/trace.hh"
55 #include "config/the_isa.hh"
56 #include "cpu/checker/cpu.hh"
57 #include "cpu/exec_context.hh"
58 #include "cpu/exetrace.hh"
59 #include "cpu/inst_res.hh"
60 #include "cpu/inst_seq.hh"
61 #include "cpu/op_class.hh"
62 #include "cpu/static_inst.hh"
63 #include "cpu/translation.hh"
64 #include "debug/HtmCpu.hh"
65 #include "mem/packet.hh"
66 #include "mem/request.hh"
67 #include "sim/byteswap.hh"
68 #include "sim/system.hh"
69
70 /**
71 * @file
72 * Defines a dynamic instruction context.
73 */
74
75 template <class Impl>
76 class BaseDynInst : public ExecContext, public RefCounted
77 {
78 public:
79 // Typedef for the CPU.
80 typedef typename Impl::CPUType ImplCPU;
81 typedef typename ImplCPU::ImplState ImplState;
82 using VecRegContainer = TheISA::VecRegContainer;
83
84 using LSQRequestPtr = typename Impl::CPUPol::LSQ::LSQRequest*;
85 using LQIterator = typename Impl::CPUPol::LSQUnit::LQIterator;
86 using SQIterator = typename Impl::CPUPol::LSQUnit::SQIterator;
87
88 // The DynInstPtr type.
89 typedef typename Impl::DynInstPtr DynInstPtr;
90 typedef RefCountingPtr<BaseDynInst<Impl> > BaseDynInstPtr;
91
92 // The list of instructions iterator type.
93 typedef typename std::list<DynInstPtr>::iterator ListIt;
94
95 enum {
96 MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs
97 MaxInstDestRegs = TheISA::MaxInstDestRegs /// Max dest regs
98 };
99
100 protected:
101 enum Status {
102 IqEntry, /// Instruction is in the IQ
103 RobEntry, /// Instruction is in the ROB
104 LsqEntry, /// Instruction is in the LSQ
105 Completed, /// Instruction has completed
106 ResultReady, /// Instruction has its result
107 CanIssue, /// Instruction can issue and execute
108 Issued, /// Instruction has issued
109 Executed, /// Instruction has executed
110 CanCommit, /// Instruction can commit
111 AtCommit, /// Instruction has reached commit
112 Committed, /// Instruction has committed
113 Squashed, /// Instruction is squashed
114 SquashedInIQ, /// Instruction is squashed in the IQ
115 SquashedInLSQ, /// Instruction is squashed in the LSQ
116 SquashedInROB, /// Instruction is squashed in the ROB
117 PinnedRegsRenamed, /// Pinned registers are renamed
118 PinnedRegsWritten, /// Pinned registers are written back
119 PinnedRegsSquashDone, /// Regs pinning status updated after squash
120 RecoverInst, /// Is a recover instruction
121 BlockingInst, /// Is a blocking instruction
122 ThreadsyncWait, /// Is a thread synchronization instruction
123 SerializeBefore, /// Needs to serialize on
124 /// instructions ahead of it
125 SerializeAfter, /// Needs to serialize instructions behind it
126 SerializeHandled, /// Serialization has been handled
127 NumStatus
128 };
129
130 enum Flags {
131 NotAnInst,
132 TranslationStarted,
133 TranslationCompleted,
134 PossibleLoadViolation,
135 HitExternalSnoop,
136 EffAddrValid,
137 RecordResult,
138 Predicate,
139 MemAccPredicate,
140 PredTaken,
141 IsStrictlyOrdered,
142 ReqMade,
143 MemOpDone,
144 HtmFromTransaction,
145 MaxFlags
146 };
147
148 public:
149 /** The sequence number of the instruction. */
150 InstSeqNum seqNum;
151
152 /** The StaticInst used by this BaseDynInst. */
153 const StaticInstPtr staticInst;
154
155 /** Pointer to the Impl's CPU object. */
156 ImplCPU *cpu;
157
158 BaseCPU *getCpuPtr() { return cpu; }
159
160 /** Pointer to the thread state. */
161 ImplState *thread;
162
163 /** The kind of fault this instruction has generated. */
164 Fault fault;
165
166 /** InstRecord that tracks this instructions. */
167 Trace::InstRecord *traceData;
168
169 protected:
170 /** The result of the instruction; assumes an instruction can have many
171 * destination registers.
172 */
173 std::queue<InstResult> instResult;
174
175 /** PC state for this instruction. */
176 TheISA::PCState pc;
177
178 private:
179 /* An amalgamation of a lot of boolean values into one */
180 std::bitset<MaxFlags> instFlags;
181
182 /** The status of this BaseDynInst. Several bits can be set. */
183 std::bitset<NumStatus> status;
184
185 protected:
186 /** Whether or not the source register is ready.
187 * @todo: Not sure this should be here vs the derived class.
188 */
189 std::bitset<MaxInstSrcRegs> _readySrcRegIdx;
190
191 public:
192 /** The thread this instruction is from. */
193 ThreadID threadNumber;
194
195 /** Iterator pointing to this BaseDynInst in the list of all insts. */
196 ListIt instListIt;
197
198 ////////////////////// Branch Data ///////////////
199 /** Predicted PC state after this instruction. */
200 TheISA::PCState predPC;
201
202 /** The Macroop if one exists */
203 const StaticInstPtr macroop;
204
205 /** How many source registers are ready. */
206 uint8_t readyRegs;
207
208 public:
209 /////////////////////// Load Store Data //////////////////////
210 /** The effective virtual address (lds & stores only). */
211 Addr effAddr;
212
213 /** The effective physical address. */
214 Addr physEffAddr;
215
216 /** The memory request flags (from translation). */
217 unsigned memReqFlags;
218
219 /** The size of the request */
220 unsigned effSize;
221
222 /** Pointer to the data for the memory access. */
223 uint8_t *memData;
224
225 /** Load queue index. */
226 int16_t lqIdx;
227 LQIterator lqIt;
228
229 /** Store queue index. */
230 int16_t sqIdx;
231 SQIterator sqIt;
232
233
234 /////////////////////// TLB Miss //////////////////////
235 /**
236 * Saved memory request (needed when the DTB address translation is
237 * delayed due to a hw page table walk).
238 */
239 LSQRequestPtr savedReq;
240
241 /////////////////////// Checker //////////////////////
242 // Need a copy of main request pointer to verify on writes.
243 RequestPtr reqToVerify;
244
245 private:
246 // hardware transactional memory
247 uint64_t htmUid;
248 uint64_t htmDepth;
249
250 protected:
251 /** Flattened register index of the destination registers of this
252 * instruction.
253 */
254 std::array<RegId, TheISA::MaxInstDestRegs> _flatDestRegIdx;
255
256 /** Physical register index of the destination registers of this
257 * instruction.
258 */
259 std::array<PhysRegIdPtr, TheISA::MaxInstDestRegs> _destRegIdx;
260
261 /** Physical register index of the source registers of this
262 * instruction.
263 */
264 std::array<PhysRegIdPtr, TheISA::MaxInstSrcRegs> _srcRegIdx;
265
266 /** Physical register index of the previous producers of the
267 * architected destinations.
268 */
269 std::array<PhysRegIdPtr, TheISA::MaxInstDestRegs> _prevDestRegIdx;
270
271
272 public:
273 /** Records changes to result? */
274 void recordResult(bool f) { instFlags[RecordResult] = f; }
275
276 /** Is the effective virtual address valid. */
277 bool effAddrValid() const { return instFlags[EffAddrValid]; }
278 void effAddrValid(bool b) { instFlags[EffAddrValid] = b; }
279
280 /** Whether or not the memory operation is done. */
281 bool memOpDone() const { return instFlags[MemOpDone]; }
282 void memOpDone(bool f) { instFlags[MemOpDone] = f; }
283
284 bool notAnInst() const { return instFlags[NotAnInst]; }
285 void setNotAnInst() { instFlags[NotAnInst] = true; }
286
287
288 ////////////////////////////////////////////
289 //
290 // INSTRUCTION EXECUTION
291 //
292 ////////////////////////////////////////////
293
294 void
295 demapPage(Addr vaddr, uint64_t asn) override
296 {
297 cpu->demapPage(vaddr, asn);
298 }
299 void
300 demapInstPage(Addr vaddr, uint64_t asn)
301 {
302 cpu->demapPage(vaddr, asn);
303 }
304 void
305 demapDataPage(Addr vaddr, uint64_t asn)
306 {
307 cpu->demapPage(vaddr, asn);
308 }
309
310 Fault initiateMemRead(Addr addr, unsigned size, Request::Flags flags,
311 const std::vector<bool> &byte_enable=std::vector<bool>()) override;
312
313 Fault initiateHtmCmd(Request::Flags flags) override;
314
315 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
316 Request::Flags flags, uint64_t *res,
317 const std::vector<bool> &byte_enable=std::vector<bool>())
318 override;
319
320 Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags,
321 AtomicOpFunctorPtr amo_op) override;
322
323 /** True if the DTB address translation has started. */
324 bool translationStarted() const { return instFlags[TranslationStarted]; }
325 void translationStarted(bool f) { instFlags[TranslationStarted] = f; }
326
327 /** True if the DTB address translation has completed. */
328 bool translationCompleted() const { return instFlags[TranslationCompleted]; }
329 void translationCompleted(bool f) { instFlags[TranslationCompleted] = f; }
330
331 /** True if this address was found to match a previous load and they issued
332 * out of order. If that happend, then it's only a problem if an incoming
333 * snoop invalidate modifies the line, in which case we need to squash.
334 * If nothing modified the line the order doesn't matter.
335 */
336 bool
337 possibleLoadViolation() const
338 {
339 return instFlags[PossibleLoadViolation];
340 }
341 void
342 possibleLoadViolation(bool f)
343 {
344 instFlags[PossibleLoadViolation] = f;
345 }
346
347 /** True if the address hit a external snoop while sitting in the LSQ.
348 * If this is true and a older instruction sees it, this instruction must
349 * reexecute
350 */
351 bool hitExternalSnoop() const { return instFlags[HitExternalSnoop]; }
352 void hitExternalSnoop(bool f) { instFlags[HitExternalSnoop] = f; }
353
354 /**
355 * Returns true if the DTB address translation is being delayed due to a hw
356 * page table walk.
357 */
358 bool
359 isTranslationDelayed() const
360 {
361 return (translationStarted() && !translationCompleted());
362 }
363
364 public:
365 #ifdef DEBUG
366 void dumpSNList();
367 #endif
368
369 /** Returns the physical register index of the i'th destination
370 * register.
371 */
372 PhysRegIdPtr
373 renamedDestRegIdx(int idx) const
374 {
375 return _destRegIdx[idx];
376 }
377
378 /** Returns the physical register index of the i'th source register. */
379 PhysRegIdPtr
380 renamedSrcRegIdx(int idx) const
381 {
382 assert(TheISA::MaxInstSrcRegs > idx);
383 return _srcRegIdx[idx];
384 }
385
386 /** Returns the flattened register index of the i'th destination
387 * register.
388 */
389 const RegId &
390 flattenedDestRegIdx(int idx) const
391 {
392 return _flatDestRegIdx[idx];
393 }
394
395 /** Returns the physical register index of the previous physical register
396 * that remapped to the same logical register index.
397 */
398 PhysRegIdPtr
399 prevDestRegIdx(int idx) const
400 {
401 return _prevDestRegIdx[idx];
402 }
403
404 /** Renames a destination register to a physical register. Also records
405 * the previous physical register that the logical register mapped to.
406 */
407 void
408 renameDestReg(int idx, PhysRegIdPtr renamed_dest,
409 PhysRegIdPtr previous_rename)
410 {
411 _destRegIdx[idx] = renamed_dest;
412 _prevDestRegIdx[idx] = previous_rename;
413 if (renamed_dest->isPinned())
414 setPinnedRegsRenamed();
415 }
416
417 /** Renames a source logical register to the physical register which
418 * has/will produce that logical register's result.
419 * @todo: add in whether or not the source register is ready.
420 */
421 void
422 renameSrcReg(int idx, PhysRegIdPtr renamed_src)
423 {
424 _srcRegIdx[idx] = renamed_src;
425 }
426
427 /** Flattens a destination architectural register index into a logical
428 * index.
429 */
430 void
431 flattenDestReg(int idx, const RegId &flattened_dest)
432 {
433 _flatDestRegIdx[idx] = flattened_dest;
434 }
435 /** BaseDynInst constructor given a binary instruction.
436 * @param staticInst A StaticInstPtr to the underlying instruction.
437 * @param pc The PC state for the instruction.
438 * @param predPC The predicted next PC state for the instruction.
439 * @param seq_num The sequence number of the instruction.
440 * @param cpu Pointer to the instruction's CPU.
441 */
442 BaseDynInst(const StaticInstPtr &staticInst, const StaticInstPtr &macroop,
443 TheISA::PCState pc, TheISA::PCState predPC,
444 InstSeqNum seq_num, ImplCPU *cpu);
445
446 /** BaseDynInst constructor given a StaticInst pointer.
447 * @param _staticInst The StaticInst for this BaseDynInst.
448 */
449 BaseDynInst(const StaticInstPtr &staticInst, const StaticInstPtr &macroop);
450
451 /** BaseDynInst destructor. */
452 ~BaseDynInst();
453
454 private:
455 /** Function to initialize variables in the constructors. */
456 void initVars();
457
458 public:
459 /** Dumps out contents of this BaseDynInst. */
460 void dump();
461
462 /** Dumps out contents of this BaseDynInst into given string. */
463 void dump(std::string &outstring);
464
465 /** Read this CPU's ID. */
466 int cpuId() const { return cpu->cpuId(); }
467
468 /** Read this CPU's Socket ID. */
469 uint32_t socketId() const { return cpu->socketId(); }
470
471 /** Read this CPU's data requestor ID */
472 MasterID masterId() const { return cpu->dataMasterId(); }
473
474 /** Read this context's system-wide ID **/
475 ContextID contextId() const { return thread->contextId(); }
476
477 /** Returns the fault type. */
478 Fault getFault() const { return fault; }
479 /** TODO: This I added for the LSQRequest side to be able to modify the
480 * fault. There should be a better mechanism in place. */
481 Fault& getFault() { return fault; }
482
483 /** Checks whether or not this instruction has had its branch target
484 * calculated yet. For now it is not utilized and is hacked to be
485 * always false.
486 * @todo: Actually use this instruction.
487 */
488 bool doneTargCalc() { return false; }
489
490 /** Set the predicted target of this current instruction. */
491 void setPredTarg(const TheISA::PCState &_predPC) { predPC = _predPC; }
492
493 const TheISA::PCState &readPredTarg() { return predPC; }
494
495 /** Returns the predicted PC immediately after the branch. */
496 Addr predInstAddr() { return predPC.instAddr(); }
497
498 /** Returns the predicted PC two instructions after the branch */
499 Addr predNextInstAddr() { return predPC.nextInstAddr(); }
500
501 /** Returns the predicted micro PC after the branch */
502 Addr predMicroPC() { return predPC.microPC(); }
503
504 /** Returns whether the instruction was predicted taken or not. */
505 bool readPredTaken() { return instFlags[PredTaken]; }
506
507 void
508 setPredTaken(bool predicted_taken)
509 {
510 instFlags[PredTaken] = predicted_taken;
511 }
512
513 /** Returns whether the instruction mispredicted. */
514 bool
515 mispredicted()
516 {
517 TheISA::PCState tempPC = pc;
518 TheISA::advancePC(tempPC, staticInst);
519 return !(tempPC == predPC);
520 }
521
522 //
523 // Instruction types. Forward checks to StaticInst object.
524 //
525 bool isNop() const { return staticInst->isNop(); }
526 bool isMemRef() const { return staticInst->isMemRef(); }
527 bool isLoad() const { return staticInst->isLoad(); }
528 bool isStore() const { return staticInst->isStore(); }
529 bool isAtomic() const { return staticInst->isAtomic(); }
530 bool isStoreConditional() const
531 { return staticInst->isStoreConditional(); }
532 bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
533 bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
534 bool isInteger() const { return staticInst->isInteger(); }
535 bool isFloating() const { return staticInst->isFloating(); }
536 bool isVector() const { return staticInst->isVector(); }
537 bool isControl() const { return staticInst->isControl(); }
538 bool isCall() const { return staticInst->isCall(); }
539 bool isReturn() const { return staticInst->isReturn(); }
540 bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
541 bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
542 bool isCondCtrl() const { return staticInst->isCondCtrl(); }
543 bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
544 bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); }
545 bool isThreadSync() const { return staticInst->isThreadSync(); }
546 bool isSerializing() const { return staticInst->isSerializing(); }
547 bool
548 isSerializeBefore() const
549 {
550 return staticInst->isSerializeBefore() || status[SerializeBefore];
551 }
552 bool
553 isSerializeAfter() const
554 {
555 return staticInst->isSerializeAfter() || status[SerializeAfter];
556 }
557 bool isSquashAfter() const { return staticInst->isSquashAfter(); }
558 bool isMemBarrier() const { return staticInst->isMemBarrier(); }
559 bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
560 bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
561 bool isQuiesce() const { return staticInst->isQuiesce(); }
562 bool isIprAccess() const { return staticInst->isIprAccess(); }
563 bool isUnverifiable() const { return staticInst->isUnverifiable(); }
564 bool isSyscall() const { return staticInst->isSyscall(); }
565 bool isMacroop() const { return staticInst->isMacroop(); }
566 bool isMicroop() const { return staticInst->isMicroop(); }
567 bool isDelayedCommit() const { return staticInst->isDelayedCommit(); }
568 bool isLastMicroop() const { return staticInst->isLastMicroop(); }
569 bool isFirstMicroop() const { return staticInst->isFirstMicroop(); }
570 bool isMicroBranch() const { return staticInst->isMicroBranch(); }
571 // hardware transactional memory
572 bool isHtmStart() const { return staticInst->isHtmStart(); }
573 bool isHtmStop() const { return staticInst->isHtmStop(); }
574 bool isHtmCancel() const { return staticInst->isHtmCancel(); }
575 bool isHtmCmd() const { return staticInst->isHtmCmd(); }
576
577 uint64_t
578 getHtmTransactionUid() const override
579 {
580 assert(instFlags[HtmFromTransaction]);
581 return this->htmUid;
582 }
583
584 uint64_t
585 newHtmTransactionUid() const override
586 {
587 panic("Not yet implemented\n");
588 return 0;
589 }
590
591 bool
592 inHtmTransactionalState() const override
593 {
594 return instFlags[HtmFromTransaction];
595 }
596
597 uint64_t
598 getHtmTransactionalDepth() const override
599 {
600 if (inHtmTransactionalState())
601 return this->htmDepth;
602 else
603 return 0;
604 }
605
606 void
607 setHtmTransactionalState(uint64_t htm_uid, uint64_t htm_depth)
608 {
609 instFlags.set(HtmFromTransaction);
610 htmUid = htm_uid;
611 htmDepth = htm_depth;
612 }
613
614 void
615 clearHtmTransactionalState()
616 {
617 if (inHtmTransactionalState()) {
618 DPRINTF(HtmCpu,
619 "clearing instuction's transactional state htmUid=%u\n",
620 getHtmTransactionUid());
621
622 instFlags.reset(HtmFromTransaction);
623 htmUid = -1;
624 htmDepth = 0;
625 }
626 }
627
628 /** Temporarily sets this instruction as a serialize before instruction. */
629 void setSerializeBefore() { status.set(SerializeBefore); }
630
631 /** Clears the serializeBefore part of this instruction. */
632 void clearSerializeBefore() { status.reset(SerializeBefore); }
633
634 /** Checks if this serializeBefore is only temporarily set. */
635 bool isTempSerializeBefore() { return status[SerializeBefore]; }
636
637 /** Temporarily sets this instruction as a serialize after instruction. */
638 void setSerializeAfter() { status.set(SerializeAfter); }
639
640 /** Clears the serializeAfter part of this instruction.*/
641 void clearSerializeAfter() { status.reset(SerializeAfter); }
642
643 /** Checks if this serializeAfter is only temporarily set. */
644 bool isTempSerializeAfter() { return status[SerializeAfter]; }
645
646 /** Sets the serialization part of this instruction as handled. */
647 void setSerializeHandled() { status.set(SerializeHandled); }
648
649 /** Checks if the serialization part of this instruction has been
650 * handled. This does not apply to the temporary serializing
651 * state; it only applies to this instruction's own permanent
652 * serializing state.
653 */
654 bool isSerializeHandled() { return status[SerializeHandled]; }
655
656 /** Returns the opclass of this instruction. */
657 OpClass opClass() const { return staticInst->opClass(); }
658
659 /** Returns the branch target address. */
660 TheISA::PCState branchTarget() const
661 { return staticInst->branchTarget(pc); }
662
663 /** Returns the number of source registers. */
664 int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
665
666 /** Returns the number of destination registers. */
667 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
668
669 // the following are used to track physical register usage
670 // for machines with separate int & FP reg files
671 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
672 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
673 int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); }
674 int8_t numVecDestRegs() const { return staticInst->numVecDestRegs(); }
675 int8_t
676 numVecElemDestRegs() const
677 {
678 return staticInst->numVecElemDestRegs();
679 }
680 int8_t
681 numVecPredDestRegs() const
682 {
683 return staticInst->numVecPredDestRegs();
684 }
685
686 /** Returns the logical register index of the i'th destination register. */
687 const RegId& destRegIdx(int i) const { return staticInst->destRegIdx(i); }
688
689 /** Returns the logical register index of the i'th source register. */
690 const RegId& srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
691
692 /** Return the size of the instResult queue. */
693 uint8_t resultSize() { return instResult.size(); }
694
695 /** Pops a result off the instResult queue.
696 * If the result stack is empty, return the default value.
697 * */
698 InstResult
699 popResult(InstResult dflt=InstResult())
700 {
701 if (!instResult.empty()) {
702 InstResult t = instResult.front();
703 instResult.pop();
704 return t;
705 }
706 return dflt;
707 }
708
709 /** Pushes a result onto the instResult queue. */
710 /** @{ */
711 /** Scalar result. */
712 template<typename T>
713 void
714 setScalarResult(T &&t)
715 {
716 if (instFlags[RecordResult]) {
717 instResult.push(InstResult(std::forward<T>(t),
718 InstResult::ResultType::Scalar));
719 }
720 }
721
722 /** Full vector result. */
723 template<typename T>
724 void
725 setVecResult(T &&t)
726 {
727 if (instFlags[RecordResult]) {
728 instResult.push(InstResult(std::forward<T>(t),
729 InstResult::ResultType::VecReg));
730 }
731 }
732
733 /** Vector element result. */
734 template<typename T>
735 void
736 setVecElemResult(T &&t)
737 {
738 if (instFlags[RecordResult]) {
739 instResult.push(InstResult(std::forward<T>(t),
740 InstResult::ResultType::VecElem));
741 }
742 }
743
744 /** Predicate result. */
745 template<typename T>
746 void
747 setVecPredResult(T &&t)
748 {
749 if (instFlags[RecordResult]) {
750 instResult.push(InstResult(std::forward<T>(t),
751 InstResult::ResultType::VecPredReg));
752 }
753 }
754 /** @} */
755
756 /** Records an integer register being set to a value. */
757 void
758 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
759 {
760 setScalarResult(val);
761 }
762
763 /** Records a CC register being set to a value. */
764 void
765 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
766 {
767 setScalarResult(val);
768 }
769
770 /** Record a vector register being set to a value */
771 void
772 setVecRegOperand(const StaticInst *si, int idx,
773 const VecRegContainer &val) override
774 {
775 setVecResult(val);
776 }
777
778 /** Records an fp register being set to an integer value. */
779 void
780 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
781 {
782 setScalarResult(val);
783 }
784
785 /** Record a vector register being set to a value */
786 void
787 setVecElemOperand(const StaticInst *si, int idx,
788 const VecElem val) override
789 {
790 setVecElemResult(val);
791 }
792
793 /** Record a vector register being set to a value */
794 void
795 setVecPredRegOperand(const StaticInst *si, int idx,
796 const VecPredRegContainer &val) override
797 {
798 setVecPredResult(val);
799 }
800
801 /** Records that one of the source registers is ready. */
802 void markSrcRegReady();
803
804 /** Marks a specific register as ready. */
805 void markSrcRegReady(RegIndex src_idx);
806
807 /** Returns if a source register is ready. */
808 bool
809 isReadySrcRegIdx(int idx) const
810 {
811 return this->_readySrcRegIdx[idx];
812 }
813
814 /** Sets this instruction as completed. */
815 void setCompleted() { status.set(Completed); }
816
817 /** Returns whether or not this instruction is completed. */
818 bool isCompleted() const { return status[Completed]; }
819
820 /** Marks the result as ready. */
821 void setResultReady() { status.set(ResultReady); }
822
823 /** Returns whether or not the result is ready. */
824 bool isResultReady() const { return status[ResultReady]; }
825
826 /** Sets this instruction as ready to issue. */
827 void setCanIssue() { status.set(CanIssue); }
828
829 /** Returns whether or not this instruction is ready to issue. */
830 bool readyToIssue() const { return status[CanIssue]; }
831
832 /** Clears this instruction being able to issue. */
833 void clearCanIssue() { status.reset(CanIssue); }
834
835 /** Sets this instruction as issued from the IQ. */
836 void setIssued() { status.set(Issued); }
837
838 /** Returns whether or not this instruction has issued. */
839 bool isIssued() const { return status[Issued]; }
840
841 /** Clears this instruction as being issued. */
842 void clearIssued() { status.reset(Issued); }
843
844 /** Sets this instruction as executed. */
845 void setExecuted() { status.set(Executed); }
846
847 /** Returns whether or not this instruction has executed. */
848 bool isExecuted() const { return status[Executed]; }
849
850 /** Sets this instruction as ready to commit. */
851 void setCanCommit() { status.set(CanCommit); }
852
853 /** Clears this instruction as being ready to commit. */
854 void clearCanCommit() { status.reset(CanCommit); }
855
856 /** Returns whether or not this instruction is ready to commit. */
857 bool readyToCommit() const { return status[CanCommit]; }
858
859 void setAtCommit() { status.set(AtCommit); }
860
861 bool isAtCommit() { return status[AtCommit]; }
862
863 /** Sets this instruction as committed. */
864 void setCommitted() { status.set(Committed); }
865
866 /** Returns whether or not this instruction is committed. */
867 bool isCommitted() const { return status[Committed]; }
868
869 /** Sets this instruction as squashed. */
870 void setSquashed();
871
872 /** Returns whether or not this instruction is squashed. */
873 bool isSquashed() const { return status[Squashed]; }
874
875 //Instruction Queue Entry
876 //-----------------------
877 /** Sets this instruction as a entry the IQ. */
878 void setInIQ() { status.set(IqEntry); }
879
880 /** Sets this instruction as a entry the IQ. */
881 void clearInIQ() { status.reset(IqEntry); }
882
883 /** Returns whether or not this instruction has issued. */
884 bool isInIQ() const { return status[IqEntry]; }
885
886 /** Sets this instruction as squashed in the IQ. */
887 void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);}
888
889 /** Returns whether or not this instruction is squashed in the IQ. */
890 bool isSquashedInIQ() const { return status[SquashedInIQ]; }
891
892
893 //Load / Store Queue Functions
894 //-----------------------
895 /** Sets this instruction as a entry the LSQ. */
896 void setInLSQ() { status.set(LsqEntry); }
897
898 /** Sets this instruction as a entry the LSQ. */
899 void removeInLSQ() { status.reset(LsqEntry); }
900
901 /** Returns whether or not this instruction is in the LSQ. */
902 bool isInLSQ() const { return status[LsqEntry]; }
903
904 /** Sets this instruction as squashed in the LSQ. */
905 void setSquashedInLSQ() { status.set(SquashedInLSQ); status.set(Squashed);}
906
907 /** Returns whether or not this instruction is squashed in the LSQ. */
908 bool isSquashedInLSQ() const { return status[SquashedInLSQ]; }
909
910
911 //Reorder Buffer Functions
912 //-----------------------
913 /** Sets this instruction as a entry the ROB. */
914 void setInROB() { status.set(RobEntry); }
915
916 /** Sets this instruction as a entry the ROB. */
917 void clearInROB() { status.reset(RobEntry); }
918
919 /** Returns whether or not this instruction is in the ROB. */
920 bool isInROB() const { return status[RobEntry]; }
921
922 /** Sets this instruction as squashed in the ROB. */
923 void setSquashedInROB() { status.set(SquashedInROB); }
924
925 /** Returns whether or not this instruction is squashed in the ROB. */
926 bool isSquashedInROB() const { return status[SquashedInROB]; }
927
928 /** Returns whether pinned registers are renamed */
929 bool isPinnedRegsRenamed() const { return status[PinnedRegsRenamed]; }
930
931 /** Sets the destination registers as renamed */
932 void
933 setPinnedRegsRenamed()
934 {
935 assert(!status[PinnedRegsSquashDone]);
936 assert(!status[PinnedRegsWritten]);
937 status.set(PinnedRegsRenamed);
938 }
939
940 /** Returns whether destination registers are written */
941 bool isPinnedRegsWritten() const { return status[PinnedRegsWritten]; }
942
943 /** Sets destination registers as written */
944 void
945 setPinnedRegsWritten()
946 {
947 assert(!status[PinnedRegsSquashDone]);
948 assert(status[PinnedRegsRenamed]);
949 status.set(PinnedRegsWritten);
950 }
951
952 /** Return whether dest registers' pinning status updated after squash */
953 bool
954 isPinnedRegsSquashDone() const { return status[PinnedRegsSquashDone]; }
955
956 /** Sets dest registers' status updated after squash */
957 void
958 setPinnedRegsSquashDone() {
959 assert(!status[PinnedRegsSquashDone]);
960 status.set(PinnedRegsSquashDone);
961 }
962
963 /** Read the PC state of this instruction. */
964 TheISA::PCState pcState() const override { return pc; }
965
966 /** Set the PC state of this instruction. */
967 void pcState(const TheISA::PCState &val) override { pc = val; }
968
969 /** Read the PC of this instruction. */
970 Addr instAddr() const { return pc.instAddr(); }
971
972 /** Read the PC of the next instruction. */
973 Addr nextInstAddr() const { return pc.nextInstAddr(); }
974
975 /**Read the micro PC of this instruction. */
976 Addr microPC() const { return pc.microPC(); }
977
978 bool readPredicate() const override { return instFlags[Predicate]; }
979
980 void
981 setPredicate(bool val) override
982 {
983 instFlags[Predicate] = val;
984
985 if (traceData) {
986 traceData->setPredicate(val);
987 }
988 }
989
990 bool
991 readMemAccPredicate() const override
992 {
993 return instFlags[MemAccPredicate];
994 }
995
996 void
997 setMemAccPredicate(bool val) override
998 {
999 instFlags[MemAccPredicate] = val;
1000 }
1001
1002 /** Sets the thread id. */
1003 void setTid(ThreadID tid) { threadNumber = tid; }
1004
1005 /** Sets the pointer to the thread state. */
1006 void setThreadState(ImplState *state) { thread = state; }
1007
1008 /** Returns the thread context. */
1009 ThreadContext *tcBase() const override { return thread->getTC(); }
1010
1011 public:
1012 /** Returns whether or not the eff. addr. source registers are ready. */
1013 bool eaSrcsReady() const;
1014
1015 /** Is this instruction's memory access strictly ordered? */
1016 bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; }
1017 void strictlyOrdered(bool so) { instFlags[IsStrictlyOrdered] = so; }
1018
1019 /** Has this instruction generated a memory request. */
1020 bool hasRequest() const { return instFlags[ReqMade]; }
1021 /** Assert this instruction has generated a memory request. */
1022 void setRequest() { instFlags[ReqMade] = true; }
1023
1024 /** Returns iterator to this instruction in the list of all insts. */
1025 ListIt &getInstListIt() { return instListIt; }
1026
1027 /** Sets iterator for this instruction in the list of all insts. */
1028 void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
1029
1030 public:
1031 /** Returns the number of consecutive store conditional failures. */
1032 unsigned int
1033 readStCondFailures() const override
1034 {
1035 return thread->storeCondFailures;
1036 }
1037
1038 /** Sets the number of consecutive store conditional failures. */
1039 void
1040 setStCondFailures(unsigned int sc_failures) override
1041 {
1042 thread->storeCondFailures = sc_failures;
1043 }
1044
1045 public:
1046 // monitor/mwait funtions
1047 void
1048 armMonitor(Addr address) override
1049 {
1050 cpu->armMonitor(threadNumber, address);
1051 }
1052 bool
1053 mwait(PacketPtr pkt) override
1054 {
1055 return cpu->mwait(threadNumber, pkt);
1056 }
1057 void
1058 mwaitAtomic(ThreadContext *tc) override
1059 {
1060 return cpu->mwaitAtomic(threadNumber, tc, cpu->dtb);
1061 }
1062 AddressMonitor *
1063 getAddrMonitor() override
1064 {
1065 return cpu->getCpuAddrMonitor(threadNumber);
1066 }
1067 };
1068
1069 template<class Impl>
1070 Fault
1071 BaseDynInst<Impl>::initiateMemRead(Addr addr, unsigned size,
1072 Request::Flags flags,
1073 const std::vector<bool> &byte_enable)
1074 {
1075 assert(byte_enable.empty() || byte_enable.size() == size);
1076 return cpu->pushRequest(
1077 dynamic_cast<typename DynInstPtr::PtrType>(this),
1078 /* ld */ true, nullptr, size, addr, flags, nullptr, nullptr,
1079 byte_enable);
1080 }
1081
1082 template<class Impl>
1083 Fault
1084 BaseDynInst<Impl>::initiateHtmCmd(Request::Flags flags)
1085 {
1086 return cpu->pushRequest(
1087 dynamic_cast<typename DynInstPtr::PtrType>(this),
1088 /* ld */ true, nullptr, 8, 0x0ul, flags, nullptr, nullptr);
1089 }
1090
1091 template<class Impl>
1092 Fault
1093 BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size, Addr addr,
1094 Request::Flags flags, uint64_t *res,
1095 const std::vector<bool> &byte_enable)
1096 {
1097 assert(byte_enable.empty() || byte_enable.size() == size);
1098 return cpu->pushRequest(
1099 dynamic_cast<typename DynInstPtr::PtrType>(this),
1100 /* st */ false, data, size, addr, flags, res, nullptr,
1101 byte_enable);
1102 }
1103
1104 template<class Impl>
1105 Fault
1106 BaseDynInst<Impl>::initiateMemAMO(Addr addr, unsigned size,
1107 Request::Flags flags,
1108 AtomicOpFunctorPtr amo_op)
1109 {
1110 // atomic memory instructions do not have data to be written to memory yet
1111 // since the atomic operations will be executed directly in cache/memory.
1112 // Therefore, its `data` field is nullptr.
1113 // Atomic memory requests need to carry their `amo_op` fields to cache/
1114 // memory
1115 return cpu->pushRequest(
1116 dynamic_cast<typename DynInstPtr::PtrType>(this),
1117 /* atomic */ false, nullptr, size, addr, flags, nullptr,
1118 std::move(amo_op));
1119 }
1120
1121 #endif // __CPU_BASE_DYN_INST_HH__