base_dyn_inst.hh (13557:fc33e6048b25) base_dyn_inst.hh (13590:d7e018859709)
1/*
1/*
2 * Copyright (c) 2011,2013,2016 ARM Limited
2 * Copyright (c) 2011, 2013, 2016-2018 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

--- 68 unchanged lines hidden (view full) ---

79class BaseDynInst : public ExecContext, public RefCounted
80{
81 public:
82 // Typedef for the CPU.
83 typedef typename Impl::CPUType ImplCPU;
84 typedef typename ImplCPU::ImplState ImplState;
85 using VecRegContainer = TheISA::VecRegContainer;
86
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

--- 68 unchanged lines hidden (view full) ---

79class BaseDynInst : public ExecContext, public RefCounted
80{
81 public:
82 // Typedef for the CPU.
83 typedef typename Impl::CPUType ImplCPU;
84 typedef typename ImplCPU::ImplState ImplState;
85 using VecRegContainer = TheISA::VecRegContainer;
86
87 using LSQRequestPtr = typename Impl::CPUPol::LSQ::LSQRequest*;
88 using LQIterator = typename Impl::CPUPol::LSQUnit::LQIterator;
89 using SQIterator = typename Impl::CPUPol::LSQUnit::SQIterator;
90
87 // The DynInstPtr type.
88 typedef typename Impl::DynInstPtr DynInstPtr;
89 typedef RefCountingPtr<BaseDynInst<Impl> > BaseDynInstPtr;
90
91 // The list of instructions iterator type.
92 typedef typename std::list<DynInstPtr>::iterator ListIt;
93
94 enum {

--- 103 unchanged lines hidden (view full) ---

198 uint8_t readyRegs;
199
200 public:
201 /////////////////////// Load Store Data //////////////////////
202 /** The effective virtual address (lds & stores only). */
203 Addr effAddr;
204
205 /** The effective physical address. */
91 // The DynInstPtr type.
92 typedef typename Impl::DynInstPtr DynInstPtr;
93 typedef RefCountingPtr<BaseDynInst<Impl> > BaseDynInstPtr;
94
95 // The list of instructions iterator type.
96 typedef typename std::list<DynInstPtr>::iterator ListIt;
97
98 enum {

--- 103 unchanged lines hidden (view full) ---

202 uint8_t readyRegs;
203
204 public:
205 /////////////////////// Load Store Data //////////////////////
206 /** The effective virtual address (lds & stores only). */
207 Addr effAddr;
208
209 /** The effective physical address. */
206 Addr physEffAddrLow;
210 Addr physEffAddr;
207
211
208 /** The effective physical address
209 * of the second request for a split request
210 */
211 Addr physEffAddrHigh;
212
213 /** The memory request flags (from translation). */
214 unsigned memReqFlags;
215
216 /** data address space ID, for loads & stores. */
217 short asid;
218
219 /** The size of the request */
220 uint8_t effSize;
221
222 /** Pointer to the data for the memory access. */
223 uint8_t *memData;
224
225 /** Load queue index. */
226 int16_t lqIdx;
212 /** The memory request flags (from translation). */
213 unsigned memReqFlags;
214
215 /** data address space ID, for loads & stores. */
216 short asid;
217
218 /** The size of the request */
219 uint8_t effSize;
220
221 /** Pointer to the data for the memory access. */
222 uint8_t *memData;
223
224 /** Load queue index. */
225 int16_t lqIdx;
226 LQIterator lqIt;
227
228 /** Store queue index. */
229 int16_t sqIdx;
227
228 /** Store queue index. */
229 int16_t sqIdx;
230 SQIterator sqIt;
230
231
232 /////////////////////// TLB Miss //////////////////////
233 /**
231
232
233 /////////////////////// TLB Miss //////////////////////
234 /**
234 * Saved memory requests (needed when the DTB address translation is
235 * Saved memory request (needed when the DTB address translation is
235 * delayed due to a hw page table walk).
236 */
236 * delayed due to a hw page table walk).
237 */
237 RequestPtr savedReq;
238 RequestPtr savedSreqLow;
239 RequestPtr savedSreqHigh;
238 LSQRequestPtr savedReq;
240
241 /////////////////////// Checker //////////////////////
242 // Need a copy of main request pointer to verify on writes.
243 RequestPtr reqToVerify;
244
245 protected:
246 /** Flattened register index of the destination registers of this
247 * instruction.

--- 17 unchanged lines hidden (view full) ---

265
266
267 public:
268 /** Records changes to result? */
269 void recordResult(bool f) { instFlags[RecordResult] = f; }
270
271 /** Is the effective virtual address valid. */
272 bool effAddrValid() const { return instFlags[EffAddrValid]; }
239
240 /////////////////////// Checker //////////////////////
241 // Need a copy of main request pointer to verify on writes.
242 RequestPtr reqToVerify;
243
244 protected:
245 /** Flattened register index of the destination registers of this
246 * instruction.

--- 17 unchanged lines hidden (view full) ---

264
265
266 public:
267 /** Records changes to result? */
268 void recordResult(bool f) { instFlags[RecordResult] = f; }
269
270 /** Is the effective virtual address valid. */
271 bool effAddrValid() const { return instFlags[EffAddrValid]; }
272 void effAddrValid(bool b) { instFlags[EffAddrValid] = b; }
273
274 /** Whether or not the memory operation is done. */
275 bool memOpDone() const { return instFlags[MemOpDone]; }
276 void memOpDone(bool f) { instFlags[MemOpDone] = f; }
277
278 bool notAnInst() const { return instFlags[NotAnInst]; }
279 void setNotAnInst() { instFlags[NotAnInst] = true; }
280

--- 17 unchanged lines hidden (view full) ---

298 cpu->demapPage(vaddr, asn);
299 }
300
301 Fault initiateMemRead(Addr addr, unsigned size, Request::Flags flags);
302
303 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
304 Request::Flags flags, uint64_t *res);
305
273
274 /** Whether or not the memory operation is done. */
275 bool memOpDone() const { return instFlags[MemOpDone]; }
276 void memOpDone(bool f) { instFlags[MemOpDone] = f; }
277
278 bool notAnInst() const { return instFlags[NotAnInst]; }
279 void setNotAnInst() { instFlags[NotAnInst] = true; }
280

--- 17 unchanged lines hidden (view full) ---

298 cpu->demapPage(vaddr, asn);
299 }
300
301 Fault initiateMemRead(Addr addr, unsigned size, Request::Flags flags);
302
303 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
304 Request::Flags flags, uint64_t *res);
305
306 /** Splits a request in two if it crosses a dcache block. */
307 void splitRequest(const RequestPtr &req, RequestPtr &sreqLow,
308 RequestPtr &sreqHigh);
309
310 /** Initiate a DTB address translation. */
311 void initiateTranslation(const RequestPtr &req, const RequestPtr &sreqLow,
312 const RequestPtr &sreqHigh, uint64_t *res,
313 BaseTLB::Mode mode);
314
315 /** Finish a DTB address translation. */
316 void finishTranslation(WholeTranslationState *state);
317
318 /** True if the DTB address translation has started. */
319 bool translationStarted() const { return instFlags[TranslationStarted]; }
320 void translationStarted(bool f) { instFlags[TranslationStarted] = f; }
321
322 /** True if the DTB address translation has completed. */
323 bool translationCompleted() const { return instFlags[TranslationCompleted]; }
324 void translationCompleted(bool f) { instFlags[TranslationCompleted] = f; }
325

--- 123 unchanged lines hidden (view full) ---

449 /** Read this CPU's data requestor ID */
450 MasterID masterId() const { return cpu->dataMasterId(); }
451
452 /** Read this context's system-wide ID **/
453 ContextID contextId() const { return thread->contextId(); }
454
455 /** Returns the fault type. */
456 Fault getFault() const { return fault; }
306 /** True if the DTB address translation has started. */
307 bool translationStarted() const { return instFlags[TranslationStarted]; }
308 void translationStarted(bool f) { instFlags[TranslationStarted] = f; }
309
310 /** True if the DTB address translation has completed. */
311 bool translationCompleted() const { return instFlags[TranslationCompleted]; }
312 void translationCompleted(bool f) { instFlags[TranslationCompleted] = f; }
313

--- 123 unchanged lines hidden (view full) ---

437 /** Read this CPU's data requestor ID */
438 MasterID masterId() const { return cpu->dataMasterId(); }
439
440 /** Read this context's system-wide ID **/
441 ContextID contextId() const { return thread->contextId(); }
442
443 /** Returns the fault type. */
444 Fault getFault() const { return fault; }
445 /** TODO: This I added for the LSQRequest side to be able to modify the
446 * fault. There should be a better mechanism in place. */
447 Fault& getFault() { return fault; }
457
458 /** Checks whether or not this instruction has had its branch target
459 * calculated yet. For now it is not utilized and is hacked to be
460 * always false.
461 * @todo: Actually use this instruction.
462 */
463 bool doneTargCalc() { return false; }
464

--- 119 unchanged lines hidden (view full) ---

584 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
585
586 // the following are used to track physical register usage
587 // for machines with separate int & FP reg files
588 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
589 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
590 int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); }
591 int8_t numVecDestRegs() const { return staticInst->numVecDestRegs(); }
448
449 /** Checks whether or not this instruction has had its branch target
450 * calculated yet. For now it is not utilized and is hacked to be
451 * always false.
452 * @todo: Actually use this instruction.
453 */
454 bool doneTargCalc() { return false; }
455

--- 119 unchanged lines hidden (view full) ---

575 int8_t numDestRegs() const { return staticInst->numDestRegs(); }
576
577 // the following are used to track physical register usage
578 // for machines with separate int & FP reg files
579 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); }
580 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
581 int8_t numCCDestRegs() const { return staticInst->numCCDestRegs(); }
582 int8_t numVecDestRegs() const { return staticInst->numVecDestRegs(); }
592 int8_t numVecElemDestRegs() const {
583 int8_t numVecElemDestRegs() const
584 {
593 return staticInst->numVecElemDestRegs();
594 }
595
596 /** Returns the logical register index of the i'th destination register. */
597 const RegId& destRegIdx(int i) const { return staticInst->destRegIdx(i); }
598
599 /** Returns the logical register index of the i'th source register. */
600 const RegId& srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }

--- 231 unchanged lines hidden (view full) ---

832
833 if (traceData) {
834 traceData->setPredicate(val);
835 }
836 }
837
838 /** Sets the ASID. */
839 void setASID(short addr_space_id) { asid = addr_space_id; }
585 return staticInst->numVecElemDestRegs();
586 }
587
588 /** Returns the logical register index of the i'th destination register. */
589 const RegId& destRegIdx(int i) const { return staticInst->destRegIdx(i); }
590
591 /** Returns the logical register index of the i'th source register. */
592 const RegId& srcRegIdx(int i) const { return staticInst->srcRegIdx(i); }

--- 231 unchanged lines hidden (view full) ---

824
825 if (traceData) {
826 traceData->setPredicate(val);
827 }
828 }
829
830 /** Sets the ASID. */
831 void setASID(short addr_space_id) { asid = addr_space_id; }
832 short getASID() { return asid; }
840
841 /** Sets the thread id. */
842 void setTid(ThreadID tid) { threadNumber = tid; }
843
844 /** Sets the pointer to the thread state. */
845 void setThreadState(ImplState *state) { thread = state; }
846
847 /** Returns the thread context. */
848 ThreadContext *tcBase() { return thread->getTC(); }
849
850 public:
851 /** Returns whether or not the eff. addr. source registers are ready. */
852 bool eaSrcsReady() const;
853
854 /** Is this instruction's memory access strictly ordered? */
855 bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; }
833
834 /** Sets the thread id. */
835 void setTid(ThreadID tid) { threadNumber = tid; }
836
837 /** Sets the pointer to the thread state. */
838 void setThreadState(ImplState *state) { thread = state; }
839
840 /** Returns the thread context. */
841 ThreadContext *tcBase() { return thread->getTC(); }
842
843 public:
844 /** Returns whether or not the eff. addr. source registers are ready. */
845 bool eaSrcsReady() const;
846
847 /** Is this instruction's memory access strictly ordered? */
848 bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; }
849 void strictlyOrdered(bool so) { instFlags[IsStrictlyOrdered] = so; }
856
857 /** Has this instruction generated a memory request. */
858 bool hasRequest() const { return instFlags[ReqMade]; }
850
851 /** Has this instruction generated a memory request. */
852 bool hasRequest() const { return instFlags[ReqMade]; }
853 /** Assert this instruction has generated a memory request. */
854 void setRequest() { instFlags[ReqMade] = true; }
859
860 /** Returns iterator to this instruction in the list of all insts. */
861 ListIt &getInstListIt() { return instListIt; }
862
863 /** Sets iterator for this instruction in the list of all insts. */
864 void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
865
866 public:

--- 15 unchanged lines hidden (view full) ---

882 { return cpu->getCpuAddrMonitor(threadNumber); }
883};
884
885template<class Impl>
886Fault
887BaseDynInst<Impl>::initiateMemRead(Addr addr, unsigned size,
888 Request::Flags flags)
889{
855
856 /** Returns iterator to this instruction in the list of all insts. */
857 ListIt &getInstListIt() { return instListIt; }
858
859 /** Sets iterator for this instruction in the list of all insts. */
860 void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; }
861
862 public:

--- 15 unchanged lines hidden (view full) ---

878 { return cpu->getCpuAddrMonitor(threadNumber); }
879};
880
881template<class Impl>
882Fault
883BaseDynInst<Impl>::initiateMemRead(Addr addr, unsigned size,
884 Request::Flags flags)
885{
890 instFlags[ReqMade] = true;
891 RequestPtr req = NULL;
892 RequestPtr sreqLow = NULL;
893 RequestPtr sreqHigh = NULL;
894
895 if (instFlags[ReqMade] && translationStarted()) {
896 req = savedReq;
897 sreqLow = savedSreqLow;
898 sreqHigh = savedSreqHigh;
899 } else {
900 req = std::make_shared<Request>(
901 asid, addr, size, flags, masterId(),
902 this->pc.instAddr(), thread->contextId());
903
904 req->taskId(cpu->taskId());
905
906 // Only split the request if the ISA supports unaligned accesses.
907 if (TheISA::HasUnalignedMemAcc) {
908 splitRequest(req, sreqLow, sreqHigh);
909 }
910 initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read);
911 }
912
913 if (translationCompleted()) {
914 if (fault == NoFault) {
915 effAddr = req->getVaddr();
916 effSize = size;
917 instFlags[EffAddrValid] = true;
918
919 if (cpu->checker) {
920 reqToVerify = std::make_shared<Request>(*req);
921 }
922 fault = cpu->read(req, sreqLow, sreqHigh, lqIdx);
923 } else {
924 // Commit will have to clean up whatever happened. Set this
925 // instruction as executed.
926 this->setExecuted();
927 }
928 }
929
930 if (traceData)
931 traceData->setMem(addr, size, flags);
932
933 return fault;
886 return cpu->pushRequest(
887 dynamic_cast<typename DynInstPtr::PtrType>(this),
888 /* ld */ true, nullptr, size, addr, flags, nullptr);
934}
935
936template<class Impl>
937Fault
938BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size, Addr addr,
939 Request::Flags flags, uint64_t *res)
940{
889}
890
891template<class Impl>
892Fault
893BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size, Addr addr,
894 Request::Flags flags, uint64_t *res)
895{
941 if (traceData)
942 traceData->setMem(addr, size, flags);
943
944 instFlags[ReqMade] = true;
945 RequestPtr req = NULL;
946 RequestPtr sreqLow = NULL;
947 RequestPtr sreqHigh = NULL;
948
949 if (instFlags[ReqMade] && translationStarted()) {
950 req = savedReq;
951 sreqLow = savedSreqLow;
952 sreqHigh = savedSreqHigh;
953 } else {
954 req = std::make_shared<Request>(
955 asid, addr, size, flags, masterId(),
956 this->pc.instAddr(), thread->contextId());
957
958 req->taskId(cpu->taskId());
959
960 // Only split the request if the ISA supports unaligned accesses.
961 if (TheISA::HasUnalignedMemAcc) {
962 splitRequest(req, sreqLow, sreqHigh);
963 }
964 initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write);
965 }
966
967 if (fault == NoFault && translationCompleted()) {
968 effAddr = req->getVaddr();
969 effSize = size;
970 instFlags[EffAddrValid] = true;
971
972 if (cpu->checker) {
973 reqToVerify = std::make_shared<Request>(*req);
974 }
975 fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx);
976 }
977
978 return fault;
896 return cpu->pushRequest(
897 dynamic_cast<typename DynInstPtr::PtrType>(this),
898 /* st */ false, data, size, addr, flags, res);
979}
980
899}
900
981template<class Impl>
982inline void
983BaseDynInst<Impl>::splitRequest(const RequestPtr &req, RequestPtr &sreqLow,
984 RequestPtr &sreqHigh)
985{
986 // Check to see if the request crosses the next level block boundary.
987 unsigned block_size = cpu->cacheLineSize();
988 Addr addr = req->getVaddr();
989 Addr split_addr = roundDown(addr + req->getSize() - 1, block_size);
990 assert(split_addr <= addr || split_addr - addr < block_size);
991
992 // Spans two blocks.
993 if (split_addr > addr) {
994 req->splitOnVaddr(split_addr, sreqLow, sreqHigh);
995 }
996}
997
998template<class Impl>
999inline void
1000BaseDynInst<Impl>::initiateTranslation(const RequestPtr &req,
1001 const RequestPtr &sreqLow,
1002 const RequestPtr &sreqHigh,
1003 uint64_t *res,
1004 BaseTLB::Mode mode)
1005{
1006 translationStarted(true);
1007
1008 if (!TheISA::HasUnalignedMemAcc || sreqLow == NULL) {
1009 WholeTranslationState *state =
1010 new WholeTranslationState(req, NULL, res, mode);
1011
1012 // One translation if the request isn't split.
1013 DataTranslation<BaseDynInstPtr> *trans =
1014 new DataTranslation<BaseDynInstPtr>(this, state);
1015
1016 cpu->dtb->translateTiming(req, thread->getTC(), trans, mode);
1017
1018 if (!translationCompleted()) {
1019 // The translation isn't yet complete, so we can't possibly have a
1020 // fault. Overwrite any existing fault we might have from a previous
1021 // execution of this instruction (e.g. an uncachable load that
1022 // couldn't execute because it wasn't at the head of the ROB).
1023 fault = NoFault;
1024
1025 // Save memory requests.
1026 savedReq = state->mainReq;
1027 savedSreqLow = state->sreqLow;
1028 savedSreqHigh = state->sreqHigh;
1029 }
1030 } else {
1031 WholeTranslationState *state =
1032 new WholeTranslationState(req, sreqLow, sreqHigh, NULL, res, mode);
1033
1034 // Two translations when the request is split.
1035 DataTranslation<BaseDynInstPtr> *stransLow =
1036 new DataTranslation<BaseDynInstPtr>(this, state, 0);
1037 DataTranslation<BaseDynInstPtr> *stransHigh =
1038 new DataTranslation<BaseDynInstPtr>(this, state, 1);
1039
1040 cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode);
1041 cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode);
1042
1043 if (!translationCompleted()) {
1044 // The translation isn't yet complete, so we can't possibly have a
1045 // fault. Overwrite any existing fault we might have from a previous
1046 // execution of this instruction (e.g. an uncachable load that
1047 // couldn't execute because it wasn't at the head of the ROB).
1048 fault = NoFault;
1049
1050 // Save memory requests.
1051 savedReq = state->mainReq;
1052 savedSreqLow = state->sreqLow;
1053 savedSreqHigh = state->sreqHigh;
1054 }
1055 }
1056}
1057
1058template<class Impl>
1059inline void
1060BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
1061{
1062 fault = state->getFault();
1063
1064 instFlags[IsStrictlyOrdered] = state->isStrictlyOrdered();
1065
1066 if (fault == NoFault) {
1067 // save Paddr for a single req
1068 physEffAddrLow = state->getPaddr();
1069
1070 // case for the request that has been split
1071 if (state->isSplit) {
1072 physEffAddrLow = state->sreqLow->getPaddr();
1073 physEffAddrHigh = state->sreqHigh->getPaddr();
1074 }
1075
1076 memReqFlags = state->getFlags();
1077
1078 if (state->mainReq->isCondSwap()) {
1079 assert(state->res);
1080 state->mainReq->setExtraData(*state->res);
1081 }
1082
1083 } else {
1084 state->deleteReqs();
1085 }
1086 delete state;
1087
1088 translationCompleted(true);
1089}
1090
1091#endif // __CPU_BASE_DYN_INST_HH__
901#endif // __CPU_BASE_DYN_INST_HH__