2 * Copyright (c) 2007 MIPS Technologies, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Korey Sewell
35 #include "arch/isa_traits.hh"
36 #include "arch/locked_mem.hh"
37 #include "arch/utility.hh"
38 #include "arch/predecoder.hh"
39 #include "config/the_isa.hh"
40 #include "cpu/inorder/resources/cache_unit.hh"
41 #include "cpu/inorder/pipeline_traits.hh"
42 #include "cpu/inorder/cpu.hh"
43 #include "mem/request.hh"
46 using namespace TheISA
;
47 using namespace ThePipeline
;
50 CacheUnit::CachePort::recvAtomic(PacketPtr pkt
)
52 panic("CacheUnit::CachePort doesn't expect recvAtomic callback!");
57 CacheUnit::CachePort::recvFunctional(PacketPtr pkt
)
59 panic("CacheUnit::CachePort doesn't expect recvFunctional callback!");
63 CacheUnit::CachePort::recvStatusChange(Status status
)
65 if (status
== RangeChange
)
68 panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
72 CacheUnit::CachePort::recvTiming(Packet
*pkt
)
74 cachePortUnit
->processCacheCompletion(pkt
);
79 CacheUnit::CachePort::recvRetry()
81 cachePortUnit
->recvRetry();
84 CacheUnit::CacheUnit(string res_name
, int res_id
, int res_width
,
85 int res_latency
, InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
86 : Resource(res_name
, res_id
, res_width
, res_latency
, _cpu
),
87 retryPkt(NULL
), retrySlot(-1), cacheBlocked(false),
90 cachePort
= new CachePort(this);
92 // Hard-Code Selection For Now
93 if (res_name
== "icache_port")
95 else if (res_name
== "dcache_port")
98 fatal("Unrecognized TLB name passed by user");
100 for (int i
=0; i
< MaxThreads
; i
++) {
101 tlbBlocked
[i
] = false;
113 CacheUnit::getPort(const string
&if_name
, int idx
)
115 if (if_name
== resName
)
124 // Currently Used to Model TLB Latency. Eventually
125 // Switch to Timing TLB translations.
126 resourceEvent
= new CacheUnitEvent
[width
];
132 CacheUnit::getSlot(DynInstPtr inst
)
134 ThreadID tid
= inst
->readTid();
136 if (tlbBlocked
[inst
->threadNumber
]) {
140 if (!inst
->validMemAddr()) {
141 panic("Mem. Addr. must be set before requesting cache access\n");
144 Addr req_addr
= inst
->getMemAddr();
146 if (resName
== "icache_port" ||
147 find(addrList
[tid
].begin(), addrList
[tid
].end(), req_addr
) == addrList
[tid
].end()) {
149 int new_slot
= Resource::getSlot(inst
);
154 inst
->memTime
= curTick
;
155 addrList
[tid
].push_back(req_addr
);
156 addrMap
[tid
][req_addr
] = inst
->seqNum
;
157 DPRINTF(InOrderCachePort
,
158 "[tid:%i]: [sn:%i]: Address %08p added to dependency list\n",
159 inst
->readTid(), inst
->seqNum
, req_addr
);
162 DPRINTF(InOrderCachePort
,
163 "[tid:%i] Denying request because there is an outstanding"
164 " request to/for addr. %08p. by [sn:%i] @ tick %i\n",
165 inst
->readTid(), req_addr
, addrMap
[tid
][req_addr
], inst
->memTime
);
171 CacheUnit::freeSlot(int slot_num
)
173 ThreadID tid
= reqMap
[slot_num
]->inst
->readTid();
175 vector
<Addr
>::iterator vect_it
= find(addrList
[tid
].begin(), addrList
[tid
].end(),
176 reqMap
[slot_num
]->inst
->getMemAddr());
177 assert(vect_it
!= addrList
[tid
].end());
179 DPRINTF(InOrderCachePort
,
180 "[tid:%i]: Address %08p removed from dependency list\n",
181 reqMap
[slot_num
]->inst
->readTid(), (*vect_it
));
183 addrList
[tid
].erase(vect_it
);
185 Resource::freeSlot(slot_num
);
189 CacheUnit::getRequest(DynInstPtr inst
, int stage_num
, int res_idx
,
190 int slot_num
, unsigned cmd
)
192 ScheduleEntry
* sched_entry
= inst
->resSched
.top();
194 if (!inst
->validMemAddr()) {
195 panic("Mem. Addr. must be set before requesting cache access\n");
198 MemCmd::Command pkt_cmd
;
200 switch (sched_entry
->cmd
)
202 case InitiateReadData
:
203 pkt_cmd
= MemCmd::ReadReq
;
205 DPRINTF(InOrderCachePort
,
206 "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
207 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
210 case InitiateWriteData
:
211 pkt_cmd
= MemCmd::WriteReq
;
213 DPRINTF(InOrderCachePort
,
214 "[tid:%i]: Write request from [sn:%i] for addr %08p\n",
215 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
219 pkt_cmd
= MemCmd::ReadReq
;
221 DPRINTF(InOrderCachePort
,
222 "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
223 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
227 panic("%i: Unexpected request type (%i) to %s", curTick
,
228 sched_entry
->cmd
, name());
231 return new CacheRequest(this, inst
, stage_num
, id
, slot_num
,
232 sched_entry
->cmd
, 0, pkt_cmd
,
233 0/*flags*/, this->cpu
->readCpuId());
237 CacheUnit::requestAgain(DynInstPtr inst
, bool &service_request
)
239 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
242 // Check to see if this instruction is requesting the same command
243 // or a different one
244 if (cache_req
->cmd
!= inst
->resSched
.top()->cmd
) {
245 // If different, then update command in the request
246 cache_req
->cmd
= inst
->resSched
.top()->cmd
;
247 DPRINTF(InOrderCachePort
,
248 "[tid:%i]: [sn:%i]: Updating the command for this "
249 "instruction\n ", inst
->readTid(), inst
->seqNum
);
251 service_request
= true;
253 // If same command, just check to see if memory access was completed
254 // but dont try to re-execute
255 DPRINTF(InOrderCachePort
,
256 "[tid:%i]: [sn:%i]: requesting this resource again\n",
257 inst
->readTid(), inst
->seqNum
);
259 service_request
= true;
264 CacheUnit::doTLBAccess(DynInstPtr inst
, CacheReqPtr cache_req
, int acc_size
,
265 int flags
, TheISA::TLB::Mode tlb_mode
)
267 ThreadID tid
= inst
->readTid();
268 Addr aligned_addr
= inst
->getMemAddr();
269 unsigned stage_num
= cache_req
->getStageNum();
270 unsigned slot_idx
= cache_req
->getSlot();
272 if (tlb_mode
== TheISA::TLB::Execute
) {
273 inst
->fetchMemReq
= new Request(inst
->readTid(), aligned_addr
,
274 acc_size
, flags
, inst
->readPC(),
275 cpu
->readCpuId(), inst
->readTid());
276 cache_req
->memReq
= inst
->fetchMemReq
;
278 inst
->dataMemReq
= new Request(inst
->readTid(), aligned_addr
,
279 acc_size
, flags
, inst
->readPC(),
280 cpu
->readCpuId(), inst
->readTid());
281 cache_req
->memReq
= inst
->dataMemReq
;
286 _tlb
->translateAtomic(cache_req
->memReq
,
287 cpu
->thread
[tid
]->getTC(), tlb_mode
);
289 if (cache_req
->fault
!= NoFault
) {
290 DPRINTF(InOrderTLB
, "[tid:%i]: %s encountered while translating "
291 "addr:%08p for [sn:%i].\n", tid
, cache_req
->fault
->name(),
292 cache_req
->memReq
->getVaddr(), inst
->seqNum
);
294 cpu
->pipelineStage
[stage_num
]->setResStall(cache_req
, tid
);
296 tlbBlocked
[tid
] = true;
298 cache_req
->tlbStall
= true;
300 scheduleEvent(slot_idx
, 1);
302 cpu
->trap(cache_req
->fault
, tid
);
304 DPRINTF(InOrderTLB
, "[tid:%i]: [sn:%i] virt. addr %08p translated "
305 "to phys. addr:%08p.\n", tid
, inst
->seqNum
,
306 cache_req
->memReq
->getVaddr(),
307 cache_req
->memReq
->getPaddr());
310 return cache_req
->fault
;
315 CacheUnit::read(DynInstPtr inst
, Addr addr
, T
&data
, unsigned flags
)
317 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
320 int acc_size
= sizeof(T
);
321 doTLBAccess(inst
, cache_req
, acc_size
, flags
, TheISA::TLB::Read
);
323 if (cache_req
->fault
== NoFault
) {
324 cache_req
->reqData
= new uint8_t[acc_size
];
325 doCacheAccess(inst
, NULL
);
328 return cache_req
->fault
;
333 CacheUnit::write(DynInstPtr inst
, T data
, Addr addr
, unsigned flags
,
336 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
339 int acc_size
= sizeof(T
);
340 doTLBAccess(inst
, cache_req
, acc_size
, flags
, TheISA::TLB::Write
);
342 if (cache_req
->fault
== NoFault
) {
343 cache_req
->reqData
= new uint8_t[acc_size
];
344 doCacheAccess(inst
, write_res
);
347 return cache_req
->fault
;
352 CacheUnit::execute(int slot_num
)
355 DPRINTF(InOrderCachePort
, "Cache Blocked. Cannot Access\n");
359 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(reqMap
[slot_num
]);
362 DynInstPtr inst
= cache_req
->inst
;
364 ThreadID tid
= inst
->readTid();
365 int seq_num
= inst
->seqNum
;
368 cache_req
->fault
= NoFault
;
370 switch (cache_req
->cmd
)
374 //@TODO: Switch to size of full cache block. Store in fetch buffer
375 int acc_size
= sizeof(TheISA::MachInst
);
377 doTLBAccess(inst
, cache_req
, acc_size
, 0, TheISA::TLB::Execute
);
379 // Only Do Access if no fault from TLB
380 if (cache_req
->fault
== NoFault
) {
382 DPRINTF(InOrderCachePort
,
383 "[tid:%u]: Initiating fetch access to %s for addr. %08p\n",
384 tid
, name(), cache_req
->inst
->getMemAddr());
386 cache_req
->reqData
= new uint8_t[acc_size
];
388 inst
->setCurResSlot(slot_num
);
396 case InitiateReadData
:
397 case InitiateWriteData
:
398 DPRINTF(InOrderCachePort
,
399 "[tid:%u]: Initiating data access to %s for addr. %08p\n",
400 tid
, name(), cache_req
->inst
->getMemAddr());
402 inst
->setCurResSlot(slot_num
);
404 if (inst
->isDataPrefetch() || inst
->isInstPrefetch()) {
413 if (cache_req
->isMemAccComplete()) {
414 DPRINTF(InOrderCachePort
,
415 "[tid:%i]: Completing Fetch Access for [sn:%i]\n",
419 DPRINTF(InOrderCachePort
, "[tid:%i]: Instruction [sn:%i] is: %s\n",
420 tid
, seq_num
, inst
->staticInst
->disassemble(inst
->PC
));
422 delete cache_req
->dataPkt
;
423 //cache_req->setMemStall(false);
426 DPRINTF(InOrderCachePort
,
427 "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
429 DPRINTF(InOrderStall
,
430 "STALL: [tid:%i]: Fetch miss from %08p\n",
431 tid
, cache_req
->inst
->readPC());
432 cache_req
->setCompleted(false);
433 //cache_req->setMemStall(true);
437 case CompleteReadData
:
438 case CompleteWriteData
:
439 DPRINTF(InOrderCachePort
,
440 "[tid:%i]: [sn:%i]: Trying to Complete Data Access\n",
443 if (cache_req
->isMemAccComplete() ||
444 inst
->isDataPrefetch() ||
445 inst
->isInstPrefetch()) {
446 cache_req
->setMemStall(false);
449 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
450 tid
, cache_req
->inst
->getMemAddr());
451 cache_req
->setCompleted(false);
452 cache_req
->setMemStall(true);
457 fatal("Unrecognized command to %s", resName
);
462 CacheUnit::prefetch(DynInstPtr inst
)
464 warn_once("Prefetching currently unimplemented");
466 CacheReqPtr cache_req
467 = dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
470 // Clean-Up cache resource request so
471 // other memory insts. can use them
472 cache_req
->setCompleted();
473 cacheStatus
= cacheAccessComplete
;
474 cacheBlocked
= false;
475 cache_req
->setMemAccPending(false);
476 cache_req
->setMemAccCompleted();
477 inst
->unsetMemAddr();
482 CacheUnit::writeHint(DynInstPtr inst
)
484 warn_once("Write Hints currently unimplemented");
486 CacheReqPtr cache_req
487 = dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
490 // Clean-Up cache resource request so
491 // other memory insts. can use them
492 cache_req
->setCompleted();
493 cacheStatus
= cacheAccessComplete
;
494 cacheBlocked
= false;
495 cache_req
->setMemAccPending(false);
496 cache_req
->setMemAccCompleted();
497 inst
->unsetMemAddr();
500 // @TODO: Split into doCacheRead() and doCacheWrite()
502 CacheUnit::doCacheAccess(DynInstPtr inst
, uint64_t *write_res
)
504 Fault fault
= NoFault
;
506 ThreadID tid
= inst
->readTid();
509 CacheReqPtr cache_req
510 = dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
513 // Check for LL/SC and if so change command
514 if (cache_req
->memReq
->isLLSC() && cache_req
->pktCmd
== MemCmd::ReadReq
) {
515 cache_req
->pktCmd
= MemCmd::LoadLockedReq
;
518 if (cache_req
->pktCmd
== MemCmd::WriteReq
) {
520 cache_req
->memReq
->isSwap() ? MemCmd::SwapReq
:
521 (cache_req
->memReq
->isLLSC() ? MemCmd::StoreCondReq
525 cache_req
->dataPkt
= new CacheReqPacket(cache_req
, cache_req
->pktCmd
,
528 if (cache_req
->dataPkt
->isRead()) {
529 cache_req
->dataPkt
->dataStatic(cache_req
->reqData
);
530 } else if (cache_req
->dataPkt
->isWrite()) {
531 cache_req
->dataPkt
->dataStatic(&cache_req
->inst
->storeData
);
533 if (cache_req
->memReq
->isCondSwap()) {
535 cache_req
->memReq
->setExtraData(*write_res
);
539 cache_req
->dataPkt
->time
= curTick
;
541 bool do_access
= true; // flag to suppress cache access
543 Request
*memReq
= cache_req
->dataPkt
->req
;
545 if (cache_req
->dataPkt
->isWrite() && cache_req
->memReq
->isLLSC()) {
546 assert(cache_req
->inst
->isStoreConditional());
547 DPRINTF(InOrderCachePort
, "Evaluating Store Conditional access\n");
548 do_access
= TheISA::handleLockedWrite(cpu
, memReq
);
551 DPRINTF(InOrderCachePort
,
552 "[tid:%i] [sn:%i] attempting to access cache\n",
556 if (!cachePort
->sendTiming(cache_req
->dataPkt
)) {
557 DPRINTF(InOrderCachePort
,
558 "[tid:%i] [sn:%i] is waiting to retry request\n",
561 retrySlot
= cache_req
->getSlot();
562 retryReq
= cache_req
;
563 retryPkt
= cache_req
->dataPkt
;
565 cacheStatus
= cacheWaitRetry
;
567 //cacheBlocked = true;
569 DPRINTF(InOrderStall
, "STALL: \n");
571 cache_req
->setCompleted(false);
573 DPRINTF(InOrderCachePort
,
574 "[tid:%i] [sn:%i] is now waiting for cache response\n",
576 cache_req
->setCompleted();
577 cache_req
->setMemAccPending();
578 cacheStatus
= cacheWaitResponse
;
579 cacheBlocked
= false;
581 } else if (!do_access
&& memReq
->isLLSC()){
582 // Store-Conditional instructions complete even if they "failed"
583 assert(cache_req
->inst
->isStoreConditional());
584 cache_req
->setCompleted(true);
587 "[tid:%i]: T%i Ignoring Failed Store Conditional Access\n",
590 processCacheCompletion(cache_req
->dataPkt
);
592 // Make cache request again since access due to
593 // inability to access
594 DPRINTF(InOrderStall
, "STALL: \n");
595 cache_req
->setCompleted(false);
602 CacheUnit::processCacheCompletion(PacketPtr pkt
)
604 // Cast to correct packet type
605 CacheReqPacket
* cache_pkt
= dynamic_cast<CacheReqPacket
*>(pkt
);
608 if (cache_pkt
->cacheReq
->isSquashed()) {
609 DPRINTF(InOrderCachePort
,
610 "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n",
611 cache_pkt
->cacheReq
->getInst()->readTid(),
612 cache_pkt
->cacheReq
->getInst()->seqNum
);
614 cache_pkt
->cacheReq
->done();
619 DPRINTF(InOrderCachePort
,
620 "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p\n",
621 cache_pkt
->cacheReq
->getInst()->readTid(),
622 cache_pkt
->cacheReq
->getInst()->seqNum
,
623 cache_pkt
->cacheReq
->getInst()->getMemAddr());
625 // Cast to correct request type
626 CacheRequest
*cache_req
= dynamic_cast<CacheReqPtr
>(
627 findRequest(cache_pkt
->cacheReq
->getInst()));
631 // Get resource request info
632 unsigned stage_num
= cache_req
->getStageNum();
633 DynInstPtr inst
= cache_req
->inst
;
634 ThreadID tid
= cache_req
->inst
->readTid();
636 if (!cache_req
->isSquashed()) {
637 if (inst
->resSched
.top()->cmd
== CompleteFetch
) {
638 DPRINTF(InOrderCachePort
,
639 "[tid:%u]: [sn:%i]: Processing fetch access\n",
642 // NOTE: This is only allowing a thread to fetch one line
643 // at a time. Re-examine when/if prefetching
645 //memcpy(fetchData[tid], cache_pkt->getPtr<uint8_t>(),
646 // cache_pkt->getSize());
648 // Get the instruction from the array of the cache line.
649 // @todo: update thsi
650 ExtMachInst ext_inst
;
651 StaticInstPtr staticInst
= NULL
;
652 Addr inst_pc
= inst
->readPC();
654 TheISA::gtoh(*reinterpret_cast<TheISA::MachInst
*>
655 (cache_pkt
->getPtr
<uint8_t>()));
657 predecoder
.setTC(cpu
->thread
[tid
]->getTC());
658 predecoder
.moreBytes(inst_pc
, inst_pc
, mach_inst
);
659 ext_inst
= predecoder
.getExtMachInst();
661 inst
->setMachInst(ext_inst
);
663 // Set Up More TraceData info
664 if (inst
->traceData
) {
665 inst
->traceData
->setStaticInst(inst
->staticInst
);
666 inst
->traceData
->setPC(inst
->readPC());
669 } else if (inst
->staticInst
&& inst
->isMemRef()) {
670 DPRINTF(InOrderCachePort
,
671 "[tid:%u]: [sn:%i]: Processing cache access\n",
674 inst
->completeAcc(pkt
);
676 if (inst
->isLoad()) {
677 assert(cache_pkt
->isRead());
679 if (cache_pkt
->req
->isLLSC()) {
680 DPRINTF(InOrderCachePort
,
681 "[tid:%u]: Handling Load-Linked for [sn:%u]\n",
683 TheISA::handleLockedRead(cpu
, cache_pkt
->req
);
686 // @NOTE: Hardcoded to for load instructions. Assumes that
687 // the dest. idx 0 is always where the data is loaded to.
688 DPRINTF(InOrderCachePort
,
689 "[tid:%u]: [sn:%i]: Data loaded was: %08p\n",
690 tid
, inst
->seqNum
, inst
->readIntResult(0));
691 DPRINTF(InOrderCachePort
,
692 "[tid:%u]: [sn:%i]: FP Data loaded was: %08p\n",
693 tid
, inst
->seqNum
, inst
->readFloatResult(0));
694 } else if(inst
->isStore()) {
695 assert(cache_pkt
->isWrite());
697 DPRINTF(InOrderCachePort
,
698 "[tid:%u]: [sn:%i]: Data stored was: FIX ME\n",
700 getMemData(cache_pkt)*/);
706 cache_req
->setMemAccPending(false);
707 cache_req
->setMemAccCompleted();
709 if (cache_req
->isMemStall() &&
710 cpu
->threadModel
== InOrderCPU::SwitchOnCacheMiss
) {
711 DPRINTF(InOrderCachePort
, "[tid:%u] Waking up from Cache Miss.\n", tid
);
713 cpu
->activateContext(tid
);
715 DPRINTF(ThreadModel
, "Activating [tid:%i] after return from cache"
719 // Wake up the CPU (if it went to sleep and was waiting on this
720 // completion event).
723 DPRINTF(Activity
, "[tid:%u] Activating %s due to cache completion\n",
724 tid
, cpu
->pipelineStage
[stage_num
]->name());
726 cpu
->switchToActive(stage_num
);
728 DPRINTF(InOrderCachePort
,
729 "[tid:%u] Miss on block @ %08p completed, but squashed\n",
730 tid
, cache_req
->inst
->readPC());
731 cache_req
->setMemAccCompleted();
734 inst
->unsetMemAddr();
738 CacheUnit::recvRetry()
740 DPRINTF(InOrderCachePort
, "Retrying Request for [tid:%i] [sn:%i]\n",
741 retryReq
->inst
->readTid(), retryReq
->inst
->seqNum
);
743 assert(retryPkt
!= NULL
);
744 assert(cacheBlocked
);
745 assert(cacheStatus
== cacheWaitRetry
);
747 if (cachePort
->sendTiming(retryPkt
)) {
748 cacheStatus
= cacheWaitResponse
;
750 cacheBlocked
= false;
752 DPRINTF(InOrderCachePort
,
753 "Retry Request for [tid:%i] [sn:%i] failed\n",
754 retryReq
->inst
->readTid(), retryReq
->inst
->seqNum
);
758 CacheUnitEvent::CacheUnitEvent()
763 CacheUnitEvent::process()
765 DynInstPtr inst
= resource
->reqMap
[slotIdx
]->inst
;
766 int stage_num
= resource
->reqMap
[slotIdx
]->getStageNum();
767 ThreadID tid
= inst
->threadNumber
;
768 CacheReqPtr req_ptr
= dynamic_cast<CacheReqPtr
>(resource
->reqMap
[slotIdx
]);
770 DPRINTF(InOrderTLB
, "Waking up from TLB Miss caused by [sn:%i].\n",
773 CacheUnit
* tlb_res
= dynamic_cast<CacheUnit
*>(resource
);
776 tlb_res
->tlbBlocked
[tid
] = false;
778 tlb_res
->cpu
->pipelineStage
[stage_num
]->
779 unsetResStall(tlb_res
->reqMap
[slotIdx
], tid
);
781 req_ptr
->tlbStall
= false;
783 if (req_ptr
->isSquashed()) {
789 CacheUnit::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
790 InstSeqNum squash_seq_num
, ThreadID tid
)
792 // If squashing due to memory stall, then we do NOT want to
793 // squash the instruction that caused the stall so we
794 // increment the sequence number here to prevent that.
796 // NOTE: This is only for the SwitchOnCacheMiss Model
797 // NOTE: If you have multiple outstanding misses from the same
798 // thread then you need to reevaluate this code
799 // NOTE: squash should originate from
800 // pipeline_stage.cc:processInstSchedule
801 DPRINTF(InOrderCachePort
, "Squashing above [sn:%u]\n",
804 squash(inst
, stage_num
, squash_seq_num
+ 1, tid
);
809 CacheUnit::squash(DynInstPtr inst
, int stage_num
,
810 InstSeqNum squash_seq_num
, ThreadID tid
)
812 vector
<int> slot_remove_list
;
814 map
<int, ResReqPtr
>::iterator map_it
= reqMap
.begin();
815 map
<int, ResReqPtr
>::iterator map_end
= reqMap
.end();
817 while (map_it
!= map_end
) {
818 ResReqPtr req_ptr
= (*map_it
).second
;
821 req_ptr
->getInst()->readTid() == tid
&&
822 req_ptr
->getInst()->seqNum
> squash_seq_num
) {
824 DPRINTF(InOrderCachePort
,
825 "[tid:%i] Squashing request from [sn:%i]\n",
826 req_ptr
->getInst()->readTid(), req_ptr
->getInst()->seqNum
);
828 req_ptr
->setSquashed();
830 req_ptr
->getInst()->setSquashed();
832 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(req_ptr
);
835 int req_slot_num
= req_ptr
->getSlot();
837 if (cache_req
->tlbStall
) {
838 tlbBlocked
[tid
] = false;
840 int stall_stage
= reqMap
[req_slot_num
]->getStageNum();
842 cpu
->pipelineStage
[stall_stage
]->
843 unsetResStall(reqMap
[req_slot_num
], tid
);
846 if (!cache_req
->tlbStall
&& !cache_req
->isMemAccPending()) {
847 // Mark request for later removal
848 cpu
->reqRemoveList
.push(req_ptr
);
850 // Mark slot for removal from resource
851 slot_remove_list
.push_back(req_ptr
->getSlot());
858 // Now Delete Slot Entry from Req. Map
859 for (int i
= 0; i
< slot_remove_list
.size(); i
++)
860 freeSlot(slot_remove_list
[i
]);
864 CacheUnit::getMemData(Packet
*packet
)
866 switch (packet
->getSize())
869 return packet
->get
<uint8_t>();
872 return packet
->get
<uint16_t>();
875 return packet
->get
<uint32_t>();
878 return packet
->get
<uint64_t>();
881 panic("bad store data size = %d\n", packet
->getSize());
885 // Extra Template Definitions
886 #ifndef DOXYGEN_SHOULD_SKIP_THIS
890 CacheUnit::read(DynInstPtr inst
, Addr addr
, Twin32_t
&data
, unsigned flags
);
894 CacheUnit::read(DynInstPtr inst
, Addr addr
, Twin64_t
&data
, unsigned flags
);
898 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint64_t &data
, unsigned flags
);
902 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint32_t &data
, unsigned flags
);
906 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint16_t &data
, unsigned flags
);
910 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint8_t &data
, unsigned flags
);
912 #endif //DOXYGEN_SHOULD_SKIP_THIS
916 CacheUnit::read(DynInstPtr inst
, Addr addr
, double &data
, unsigned flags
)
918 return read(inst
, addr
, *(uint64_t*)&data
, flags
);
923 CacheUnit::read(DynInstPtr inst
, Addr addr
, float &data
, unsigned flags
)
925 return read(inst
, addr
, *(uint32_t*)&data
, flags
);
931 CacheUnit::read(DynInstPtr inst
, Addr addr
, int32_t &data
, unsigned flags
)
933 return read(inst
, addr
, (uint32_t&)data
, flags
);
936 #ifndef DOXYGEN_SHOULD_SKIP_THIS
940 CacheUnit::write(DynInstPtr inst
, Twin32_t data
, Addr addr
,
941 unsigned flags
, uint64_t *res
);
945 CacheUnit::write(DynInstPtr inst
, Twin64_t data
, Addr addr
,
946 unsigned flags
, uint64_t *res
);
950 CacheUnit::write(DynInstPtr inst
, uint64_t data
, Addr addr
,
951 unsigned flags
, uint64_t *res
);
955 CacheUnit::write(DynInstPtr inst
, uint32_t data
, Addr addr
,
956 unsigned flags
, uint64_t *res
);
960 CacheUnit::write(DynInstPtr inst
, uint16_t data
, Addr addr
,
961 unsigned flags
, uint64_t *res
);
965 CacheUnit::write(DynInstPtr inst
, uint8_t data
, Addr addr
,
966 unsigned flags
, uint64_t *res
);
968 #endif //DOXYGEN_SHOULD_SKIP_THIS
972 CacheUnit::write(DynInstPtr inst
, double data
, Addr addr
, unsigned flags
,
975 return write(inst
, *(uint64_t*)&data
, addr
, flags
, res
);
980 CacheUnit::write(DynInstPtr inst
, float data
, Addr addr
, unsigned flags
,
983 return write(inst
, *(uint32_t*)&data
, addr
, flags
, res
);
989 CacheUnit::write(DynInstPtr inst
, int32_t data
, Addr addr
, unsigned flags
,
992 return write(inst
, (uint32_t)data
, addr
, flags
, res
);