cpu: Get rid of the IsThreadSync StaticInst flag.
[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 RequestorID requestorId() const { return cpu->dataRequestorId(); }
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 isSerializing() const { return staticInst->isSerializing(); }
545 bool
546 isSerializeBefore() const
547 {
548 return staticInst->isSerializeBefore() || status[SerializeBefore];
549 }
550 bool
551 isSerializeAfter() const
552 {
553 return staticInst->isSerializeAfter() || status[SerializeAfter];
554 }
555 bool isSquashAfter() const { return staticInst->isSquashAfter(); }
556 bool isMemBarrier() const { return staticInst->isMemBarrier(); }
557 bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
558 bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
559 bool isQuiesce() const { return staticInst->isQuiesce(); }
560 bool isIprAccess() const { return staticInst->isIprAccess(); }
561 bool isUnverifiable() const { return staticInst->isUnverifiable(); }
562 bool isSyscall() const { return staticInst->isSyscall(); }
563 bool isMacroop() const { return staticInst->isMacroop(); }
564 bool isMicroop() const { return staticInst->isMicroop(); }
565 bool isDelayedCommit() const { return staticInst->isDelayedCommit(); }
566 bool isLastMicroop() const { return staticInst->isLastMicroop(); }
567 bool isFirstMicroop() const { return staticInst->isFirstMicroop(); }
568 bool isMicroBranch() const { return staticInst->isMicroBranch(); }
569 // hardware transactional memory
570 bool isHtmStart() const { return staticInst->isHtmStart(); }
571 bool isHtmStop() const { return staticInst->isHtmStop(); }
572 bool isHtmCancel() const { return staticInst->isHtmCancel(); }
573 bool isHtmCmd() const { return staticInst->isHtmCmd(); }
574
575 uint64_t
576 getHtmTransactionUid() const override
577 {
578 assert(instFlags[HtmFromTransaction]);
579 return this->htmUid;
580 }
581
582 uint64_t
583 newHtmTransactionUid() const override
584 {
585 panic("Not yet implemented\n");
586 return 0;
587 }
588
589 bool
590 inHtmTransactionalState() const override
591 {
592 return instFlags[HtmFromTransaction];
593 }
594
595 uint64_t
596 getHtmTransactionalDepth() const override
597 {
598 if (inHtmTransactionalState())
599 return this->htmDepth;
600 else
601 return 0;
602 }
603
604 void
605 setHtmTransactionalState(uint64_t htm_uid, uint64_t htm_depth)
606 {
607 instFlags.set(HtmFromTransaction);
608 htmUid = htm_uid;
609 htmDepth = htm_depth;
610 }
611
612 void
613 clearHtmTransactionalState()
614 {
615 if (inHtmTransactionalState()) {
616 DPRINTF(HtmCpu,
617 "clearing instuction's transactional state htmUid=%u\n",
618 getHtmTransactionUid());
619
620 instFlags.reset(HtmFromTransaction);
621 htmUid = -1;
622 htmDepth = 0;
623 }
624 }
625
626 /** Temporarily sets this instruction as a serialize before instruction. */
627 void setSerializeBefore() { status.set(SerializeBefore); }
628
629 /** Clears the serializeBefore part of this instruction. */
630 void clearSerializeBefore() { status.reset(SerializeBefore); }
631
632 /** Checks if this serializeBefore is only temporarily set. */
633 bool isTempSerializeBefore() { return status[SerializeBefore]; }
634
635 /** Temporarily sets this instruction as a serialize after instruction. */
636 void setSerializeAfter() { status.set(SerializeAfter); }
637
638 /** Clears the serializeAfter part of this instruction.*/
639 void clearSerializeAfter() { status.reset(SerializeAfter); }
640
641 /** Checks if this serializeAfter is only temporarily set. */
642 bool isTempSerializeAfter() { return status[SerializeAfter]; }
643
644 /** Sets the serialization part of this instruction as handled. */
645 void setSerializeHandled() { status.set(SerializeHandled); }
646
647 /** Checks if the serialization part of this instruction has been
648 * handled. This does not apply to the temporary serializing
649 * state; it only applies to this instruction's own permanent
650 * serializing state.
651 */
652 bool isSerializeHandled() { return status[SerializeHandled]; }
653
654 /** Returns the opclass of this instruction. */
655 OpClass opClass() const { return staticInst->opClass(); }
656
657 /** Returns the branch target address. */
658 TheISA::PCState branchTarget() const
659 { return staticInst->branchTarget(pc); }
660
661 /** Returns the number of source registers. */
662 int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
663
664 /** Returns the number of destination registers. */
665 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
666
667 // the following are used to track physical register usage
668 // for machines with separate int & FP reg files
669 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
670 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
671 int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); }
672 int8_t numVecDestRegs() const { return staticInst->numVecDestRegs(); }
673 int8_t
674 numVecElemDestRegs() const
675 {
676 return staticInst->numVecElemDestRegs();
677 }
678 int8_t
679 numVecPredDestRegs() const
680 {
681 return staticInst->numVecPredDestRegs();
682 }
683
684 /** Returns the logical register index of the i'th destination register. */
685 const RegId& destRegIdx(int i) const { return staticInst->destRegIdx(i); }
686
687 /** Returns the logical register index of the i'th source register. */
688 const RegId& srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }
689
690 /** Return the size of the instResult queue. */
691 uint8_t resultSize() { return instResult.size(); }
692
693 /** Pops a result off the instResult queue.
694 * If the result stack is empty, return the default value.
695 * */
696 InstResult
697 popResult(InstResult dflt=InstResult())
698 {
699 if (!instResult.empty()) {
700 InstResult t = instResult.front();
701 instResult.pop();
702 return t;
703 }
704 return dflt;
705 }
706
707 /** Pushes a result onto the instResult queue. */
708 /** @{ */
709 /** Scalar result. */
710 template<typename T>
711 void
712 setScalarResult(T &&t)
713 {
714 if (instFlags[RecordResult]) {
715 instResult.push(InstResult(std::forward<T>(t),
716 InstResult::ResultType::Scalar));
717 }
718 }
719
720 /** Full vector result. */
721 template<typename T>
722 void
723 setVecResult(T &&t)
724 {
725 if (instFlags[RecordResult]) {
726 instResult.push(InstResult(std::forward<T>(t),
727 InstResult::ResultType::VecReg));
728 }
729 }
730
731 /** Vector element result. */
732 template<typename T>
733 void
734 setVecElemResult(T &&t)
735 {
736 if (instFlags[RecordResult]) {
737 instResult.push(InstResult(std::forward<T>(t),
738 InstResult::ResultType::VecElem));
739 }
740 }
741
742 /** Predicate result. */
743 template<typename T>
744 void
745 setVecPredResult(T &&t)
746 {
747 if (instFlags[RecordResult]) {
748 instResult.push(InstResult(std::forward<T>(t),
749 InstResult::ResultType::VecPredReg));
750 }
751 }
752 /** @} */
753
754 /** Records an integer register being set to a value. */
755 void
756 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
757 {
758 setScalarResult(val);
759 }
760
761 /** Records a CC register being set to a value. */
762 void
763 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
764 {
765 setScalarResult(val);
766 }
767
768 /** Record a vector register being set to a value */
769 void
770 setVecRegOperand(const StaticInst *si, int idx,
771 const VecRegContainer &val) override
772 {
773 setVecResult(val);
774 }
775
776 /** Records an fp register being set to an integer value. */
777 void
778 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
779 {
780 setScalarResult(val);
781 }
782
783 /** Record a vector register being set to a value */
784 void
785 setVecElemOperand(const StaticInst *si, int idx,
786 const VecElem val) override
787 {
788 setVecElemResult(val);
789 }
790
791 /** Record a vector register being set to a value */
792 void
793 setVecPredRegOperand(const StaticInst *si, int idx,
794 const VecPredRegContainer &val) override
795 {
796 setVecPredResult(val);
797 }
798
799 /** Records that one of the source registers is ready. */
800 void markSrcRegReady();
801
802 /** Marks a specific register as ready. */
803 void markSrcRegReady(RegIndex src_idx);
804
805 /** Returns if a source register is ready. */
806 bool
807 isReadySrcRegIdx(int idx) const
808 {
809 return this->_readySrcRegIdx[idx];
810 }
811
812 /** Sets this instruction as completed. */
813 void setCompleted() { status.set(Completed); }
814
815 /** Returns whether or not this instruction is completed. */
816 bool isCompleted() const { return status[Completed]; }
817
818 /** Marks the result as ready. */
819 void setResultReady() { status.set(ResultReady); }
820
821 /** Returns whether or not the result is ready. */
822 bool isResultReady() const { return status[ResultReady]; }
823
824 /** Sets this instruction as ready to issue. */
825 void setCanIssue() { status.set(CanIssue); }
826
827 /** Returns whether or not this instruction is ready to issue. */
828 bool readyToIssue() const { return status[CanIssue]; }
829
830 /** Clears this instruction being able to issue. */
831 void clearCanIssue() { status.reset(CanIssue); }
832
833 /** Sets this instruction as issued from the IQ. */
834 void setIssued() { status.set(Issued); }
835
836 /** Returns whether or not this instruction has issued. */
837 bool isIssued() const { return status[Issued]; }
838
839 /** Clears this instruction as being issued. */
840 void clearIssued() { status.reset(Issued); }
841
842 /** Sets this instruction as executed. */
843 void setExecuted() { status.set(Executed); }
844
845 /** Returns whether or not this instruction has executed. */
846 bool isExecuted() const { return status[Executed]; }
847
848 /** Sets this instruction as ready to commit. */
849 void setCanCommit() { status.set(CanCommit); }
850
851 /** Clears this instruction as being ready to commit. */
852 void clearCanCommit() { status.reset(CanCommit); }
853
854 /** Returns whether or not this instruction is ready to commit. */
855 bool readyToCommit() const { return status[CanCommit]; }
856
857 void setAtCommit() { status.set(AtCommit); }
858
859 bool isAtCommit() { return status[AtCommit]; }
860
861 /** Sets this instruction as committed. */
862 void setCommitted() { status.set(Committed); }
863
864 /** Returns whether or not this instruction is committed. */
865 bool isCommitted() const { return status[Committed]; }
866
867 /** Sets this instruction as squashed. */
868 void setSquashed();
869
870 /** Returns whether or not this instruction is squashed. */
871 bool isSquashed() const { return status[Squashed]; }
872
873 //Instruction Queue Entry
874 //-----------------------
875 /** Sets this instruction as a entry the IQ. */
876 void setInIQ() { status.set(IqEntry); }
877
878 /** Sets this instruction as a entry the IQ. */
879 void clearInIQ() { status.reset(IqEntry); }
880
881 /** Returns whether or not this instruction has issued. */
882 bool isInIQ() const { return status[IqEntry]; }
883
884 /** Sets this instruction as squashed in the IQ. */
885 void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);}
886
887 /** Returns whether or not this instruction is squashed in the IQ. */
888 bool isSquashedInIQ() const { return status[SquashedInIQ]; }
889
890
891 //Load / Store Queue Functions
892 //-----------------------
893 /** Sets this instruction as a entry the LSQ. */
894 void setInLSQ() { status.set(LsqEntry); }
895
896 /** Sets this instruction as a entry the LSQ. */
897 void removeInLSQ() { status.reset(LsqEntry); }
898
899 /** Returns whether or not this instruction is in the LSQ. */
900 bool isInLSQ() const { return status[LsqEntry]; }
901
902 /** Sets this instruction as squashed in the LSQ. */
903 void setSquashedInLSQ() { status.set(SquashedInLSQ); status.set(Squashed);}
904
905 /** Returns whether or not this instruction is squashed in the LSQ. */
906 bool isSquashedInLSQ() const { return status[SquashedInLSQ]; }
907
908
909 //Reorder Buffer Functions
910 //-----------------------
911 /** Sets this instruction as a entry the ROB. */
912 void setInROB() { status.set(RobEntry); }
913
914 /** Sets this instruction as a entry the ROB. */
915 void clearInROB() { status.reset(RobEntry); }
916
917 /** Returns whether or not this instruction is in the ROB. */
918 bool isInROB() const { return status[RobEntry]; }
919
920 /** Sets this instruction as squashed in the ROB. */
921 void setSquashedInROB() { status.set(SquashedInROB); }
922
923 /** Returns whether or not this instruction is squashed in the ROB. */
924 bool isSquashedInROB() const { return status[SquashedInROB]; }
925
926 /** Returns whether pinned registers are renamed */
927 bool isPinnedRegsRenamed() const { return status[PinnedRegsRenamed]; }
928
929 /** Sets the destination registers as renamed */
930 void
931 setPinnedRegsRenamed()
932 {
933 assert(!status[PinnedRegsSquashDone]);
934 assert(!status[PinnedRegsWritten]);
935 status.set(PinnedRegsRenamed);
936 }
937
938 /** Returns whether destination registers are written */
939 bool isPinnedRegsWritten() const { return status[PinnedRegsWritten]; }
940
941 /** Sets destination registers as written */
942 void
943 setPinnedRegsWritten()
944 {
945 assert(!status[PinnedRegsSquashDone]);
946 assert(status[PinnedRegsRenamed]);
947 status.set(PinnedRegsWritten);
948 }
949
950 /** Return whether dest registers' pinning status updated after squash */
951 bool
952 isPinnedRegsSquashDone() const { return status[PinnedRegsSquashDone]; }
953
954 /** Sets dest registers' status updated after squash */
955 void
956 setPinnedRegsSquashDone() {
957 assert(!status[PinnedRegsSquashDone]);
958 status.set(PinnedRegsSquashDone);
959 }
960
961 /** Read the PC state of this instruction. */
962 TheISA::PCState pcState() const override { return pc; }
963
964 /** Set the PC state of this instruction. */
965 void pcState(const TheISA::PCState &val) override { pc = val; }
966
967 /** Read the PC of this instruction. */
968 Addr instAddr() const { return pc.instAddr(); }
969
970 /** Read the PC of the next instruction. */
971 Addr nextInstAddr() const { return pc.nextInstAddr(); }
972
973 /**Read the micro PC of this instruction. */
974 Addr microPC() const { return pc.microPC(); }
975
976 bool readPredicate() const override { return instFlags[Predicate]; }
977
978 void
979 setPredicate(bool val) override
980 {
981 instFlags[Predicate] = val;
982
983 if (traceData) {
984 traceData->setPredicate(val);
985 }
986 }
987
988 bool
989 readMemAccPredicate() const override
990 {
991 return instFlags[MemAccPredicate];
992 }
993
994 void
995 setMemAccPredicate(bool val) override
996 {
997 instFlags[MemAccPredicate] = val;
998 }
999
1000 /** Sets the thread id. */
1001 void setTid(ThreadID tid) { threadNumber = tid; }
1002
1003 /** Sets the pointer to the thread state. */
1004 void setThreadState(ImplState *state) { thread = state; }
1005
1006 /** Returns the thread context. */
1007 ThreadContext *tcBase() const override { return thread->getTC(); }
1008
1009 public:
1010 /** Returns whether or not the eff. addr. source registers are ready. */
1011 bool eaSrcsReady() const;
1012
1013 /** Is this instruction's memory access strictly ordered? */
1014 bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; }
1015 void strictlyOrdered(bool so) { instFlags[IsStrictlyOrdered] = so; }
1016
1017 /** Has this instruction generated a memory request. */
1018 bool hasRequest() const { return instFlags[ReqMade]; }
1019 /** Assert this instruction has generated a memory request. */
1020 void setRequest() { instFlags[ReqMade] = true; }
1021
1022 /** Returns iterator to this instruction in the list of all insts. */
1023 ListIt &getInstListIt() { return instListIt; }
1024
1025 /** Sets iterator for this instruction in the list of all insts. */
1026 void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
1027
1028 public:
1029 /** Returns the number of consecutive store conditional failures. */
1030 unsigned int
1031 readStCondFailures() const override
1032 {
1033 return thread->storeCondFailures;
1034 }
1035
1036 /** Sets the number of consecutive store conditional failures. */
1037 void
1038 setStCondFailures(unsigned int sc_failures) override
1039 {
1040 thread->storeCondFailures = sc_failures;
1041 }
1042
1043 public:
1044 // monitor/mwait funtions
1045 void
1046 armMonitor(Addr address) override
1047 {
1048 cpu->armMonitor(threadNumber, address);
1049 }
1050 bool
1051 mwait(PacketPtr pkt) override
1052 {
1053 return cpu->mwait(threadNumber, pkt);
1054 }
1055 void
1056 mwaitAtomic(ThreadContext *tc) override
1057 {
1058 return cpu->mwaitAtomic(threadNumber, tc, cpu->dtb);
1059 }
1060 AddressMonitor *
1061 getAddrMonitor() override
1062 {
1063 return cpu->getCpuAddrMonitor(threadNumber);
1064 }
1065 };
1066
1067 template<class Impl>
1068 Fault
1069 BaseDynInst<Impl>::initiateMemRead(Addr addr, unsigned size,
1070 Request::Flags flags,
1071 const std::vector<bool> &byte_enable)
1072 {
1073 assert(byte_enable.empty() || byte_enable.size() == size);
1074 return cpu->pushRequest(
1075 dynamic_cast<typename DynInstPtr::PtrType>(this),
1076 /* ld */ true, nullptr, size, addr, flags, nullptr, nullptr,
1077 byte_enable);
1078 }
1079
1080 template<class Impl>
1081 Fault
1082 BaseDynInst<Impl>::initiateHtmCmd(Request::Flags flags)
1083 {
1084 return cpu->pushRequest(
1085 dynamic_cast<typename DynInstPtr::PtrType>(this),
1086 /* ld */ true, nullptr, 8, 0x0ul, flags, nullptr, nullptr);
1087 }
1088
1089 template<class Impl>
1090 Fault
1091 BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size, Addr addr,
1092 Request::Flags flags, uint64_t *res,
1093 const std::vector<bool> &byte_enable)
1094 {
1095 assert(byte_enable.empty() || byte_enable.size() == size);
1096 return cpu->pushRequest(
1097 dynamic_cast<typename DynInstPtr::PtrType>(this),
1098 /* st */ false, data, size, addr, flags, res, nullptr,
1099 byte_enable);
1100 }
1101
1102 template<class Impl>
1103 Fault
1104 BaseDynInst<Impl>::initiateMemAMO(Addr addr, unsigned size,
1105 Request::Flags flags,
1106 AtomicOpFunctorPtr amo_op)
1107 {
1108 // atomic memory instructions do not have data to be written to memory yet
1109 // since the atomic operations will be executed directly in cache/memory.
1110 // Therefore, its `data` field is nullptr.
1111 // Atomic memory requests need to carry their `amo_op` fields to cache/
1112 // memory
1113 return cpu->pushRequest(
1114 dynamic_cast<typename DynInstPtr::PtrType>(this),
1115 /* atomic */ false, nullptr, size, addr, flags, nullptr,
1116 std::move(amo_op));
1117 }
1118
1119 #endif // __CPU_BASE_DYN_INST_HH__