2 * Copyright (c) 2013 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2007 MIPS Technologies, Inc.
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Korey Sewell
47 #include "arch/isa_traits.hh"
48 #include "arch/locked_mem.hh"
49 #include "arch/utility.hh"
50 #include "config/the_isa.hh"
51 #include "cpu/inorder/resources/cache_unit.hh"
52 #include "cpu/inorder/cpu.hh"
53 #include "cpu/inorder/pipeline_traits.hh"
54 #include "cpu/inorder/resource_pool.hh"
55 #include "debug/Activity.hh"
56 #include "debug/AddrDep.hh"
57 #include "debug/InOrderCachePort.hh"
58 #include "debug/InOrderStall.hh"
59 #include "debug/InOrderTLB.hh"
60 #include "debug/LLSC.hh"
61 #include "debug/RefCount.hh"
62 #include "debug/ThreadModel.hh"
63 #include "mem/request.hh"
66 using namespace TheISA
;
67 using namespace ThePipeline
;
71 printMemData(uint8_t *data
, unsigned size
)
73 std::stringstream dataStr
;
74 for (unsigned pos
= 0; pos
< size
; pos
++) {
75 ccprintf(dataStr
, "%02x", data
[pos
]);
81 CacheUnit::CacheUnit(string res_name
, int res_id
, int res_width
,
82 Cycles res_latency
, InOrderCPU
*_cpu
,
83 ThePipeline::Params
*params
)
84 : Resource(res_name
, res_id
, res_width
, res_latency
, _cpu
),
85 cachePort(NULL
), cachePortBlocked(false)
87 // Hard-Code Selection For Now
90 else if (res_id
== DCache
)
93 fatal("Unrecognized TLB name passed by user");
95 // Note that the CPU port is not yet instantiated (as it is done
96 // after the resource pool), we delay setting the cachePort
97 // pointer until init().
99 for (int i
=0; i
< MaxThreads
; i
++) {
100 tlbBlocked
[i
] = false;
101 tlbBlockSeqNum
[i
] = 0;
115 // Get the appropriate port from the CPU based on the resource name.
117 cachePort
= &cpu
->getInstPort();
118 } else if (id
== DCache
) {
119 cachePort
= &cpu
->getDataPort();
121 assert(cachePort
!= NULL
);
123 for (int i
= 0; i
< width
; i
++) {
124 reqs
[i
] = new CacheRequest(this);
127 cacheBlkSize
= cpu
->cacheLineSize();
128 cacheBlkMask
= cacheBlkSize
- 1;
134 CacheUnit::getSlot(DynInstPtr inst
)
136 ThreadID tid
= inst
->readTid();
137 if (tlbBlocked
[tid
]) {
141 // For a Split-Load, the instruction would have processed once already
142 // causing the address to be unset.
143 if (!inst
->validMemAddr() && !inst
->splitInst
) {
144 panic("[tid:%i][sn:%i] Mem. Addr. must be set before requesting "
145 "cache access\n", inst
->readTid(), inst
->seqNum
);
148 int new_slot
= Resource::getSlot(inst
);
149 inst
->memTime
= curTick();
150 //@note: add back in if you want speculative loads/store capability
151 //setAddrDependency(inst);
156 CacheUnit::setAddrDependency(DynInstPtr inst
)
158 Addr req_addr
= inst
->getMemAddr();
159 ThreadID tid
= inst
->readTid();
161 addrList
[tid
].push_back(req_addr
);
162 addrMap
[tid
][req_addr
] = inst
->seqNum
;
165 "[tid:%i]: [sn:%i]: Address %08p added to dependency list (size=%i)\n",
166 inst
->readTid(), inst
->seqNum
, req_addr
, addrList
[tid
].size());
168 //@NOTE: 10 is an arbitrarily "high" number, but to be exact
169 // we would need to know the # of outstanding accesses
170 // a priori. Information like fetch width, stage width,
171 // fetch buffer, and the branch resolution stage would be
172 // useful for the icache_port. For the dcache port, the #
173 // of outstanding cache accesses (mshrs) would be a good
174 // sanity check here.
175 //assert(addrList[tid].size() < 10);
179 CacheUnit::removeAddrDependency(DynInstPtr inst
)
181 ThreadID tid
= inst
->readTid();
183 Addr mem_addr
= inst
->getMemAddr();
185 inst
->unsetMemAddr();
187 // Erase from Address List
188 std::list
<Addr
>::iterator list_it
= find(addrList
[tid
].begin(),
191 assert(list_it
!= addrList
[tid
].end() || inst
->splitInst
);
193 if (list_it
!= addrList
[tid
].end()) {
195 "[tid:%i]: [sn:%i] Address %08p removed from dependency "
196 "list\n", inst
->readTid(), inst
->seqNum
, (*list_it
));
198 addrList
[tid
].erase(list_it
);
200 // Erase From Address Map (Used for Debugging)
201 addrMap
[tid
].erase(addrMap
[tid
].find(mem_addr
));
208 CacheUnit::findRequest(DynInstPtr inst
)
210 for (int i
= 0; i
< width
; i
++) {
211 CacheRequest
* cache_req
=
212 dynamic_cast<CacheRequest
*>(reqs
[i
]);
215 if (cache_req
->valid
&&
216 cache_req
->getInst() == inst
&&
217 cache_req
->instIdx
== inst
->curSkedEntry
->idx
) {
226 CacheUnit::findRequest(DynInstPtr inst
, int idx
)
228 for (int i
= 0; i
< width
; i
++) {
229 CacheRequest
* cache_req
=
230 dynamic_cast<CacheRequest
*>(reqs
[i
]);
233 if (cache_req
->valid
&&
234 cache_req
->getInst() == inst
&&
235 cache_req
->instIdx
== idx
) {
245 CacheUnit::getRequest(DynInstPtr inst
, int stage_num
, int res_idx
,
246 int slot_num
, unsigned cmd
)
248 ScheduleEntry
* sched_entry
= *inst
->curSkedEntry
;
249 CacheRequest
* cache_req
= dynamic_cast<CacheRequest
*>(reqs
[slot_num
]);
251 if (!inst
->validMemAddr()) {
252 panic("Mem. Addr. must be set before requesting cache access\n");
255 MemCmd::Command pkt_cmd
;
257 switch (sched_entry
->cmd
)
259 case InitSecondSplitRead
:
260 pkt_cmd
= MemCmd::ReadReq
;
262 DPRINTF(InOrderCachePort
,
263 "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
264 inst
->readTid(), inst
->seqNum
, inst
->split2ndAddr
);
267 case InitiateReadData
:
268 pkt_cmd
= MemCmd::ReadReq
;
270 DPRINTF(InOrderCachePort
,
271 "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
272 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
275 case InitSecondSplitWrite
:
276 pkt_cmd
= MemCmd::WriteReq
;
278 DPRINTF(InOrderCachePort
,
279 "[tid:%i]: Write request from [sn:%i] for addr %08p\n",
280 inst
->readTid(), inst
->seqNum
, inst
->split2ndAddr
);
283 case InitiateWriteData
:
284 pkt_cmd
= MemCmd::WriteReq
;
286 DPRINTF(InOrderCachePort
,
287 "[tid:%i]: Write request from [sn:%i] for addr %08p\n",
288 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
292 panic("%i: Unexpected request type (%i) to %s", curTick(),
293 sched_entry
->cmd
, name());
296 cache_req
->setRequest(inst
, stage_num
, id
, slot_num
,
297 sched_entry
->cmd
, pkt_cmd
,
298 inst
->curSkedEntry
->idx
);
303 CacheUnit::requestAgain(DynInstPtr inst
, bool &service_request
)
305 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
308 // Check to see if this instruction is requesting the same command
309 // or a different one
310 if (cache_req
->cmd
!= inst
->curSkedEntry
->cmd
&&
311 cache_req
->instIdx
== inst
->curSkedEntry
->idx
) {
312 // If different, then update command in the request
313 cache_req
->cmd
= inst
->curSkedEntry
->cmd
;
314 DPRINTF(InOrderCachePort
,
315 "[tid:%i]: [sn:%i]: Updating the command for this "
316 "instruction\n", inst
->readTid(), inst
->seqNum
);
318 service_request
= true;
319 } else if (inst
->curSkedEntry
->idx
!= CacheUnit::InitSecondSplitRead
&&
320 inst
->curSkedEntry
->idx
!= CacheUnit::InitSecondSplitWrite
) {
321 // If same command, just check to see if memory access was completed
322 // but dont try to re-execute
323 DPRINTF(InOrderCachePort
,
324 "[tid:%i]: [sn:%i]: requesting this resource again\n",
325 inst
->readTid(), inst
->seqNum
);
327 service_request
= true;
332 CacheUnit::setupMemRequest(DynInstPtr inst
, CacheReqPtr cache_req
,
333 int acc_size
, int flags
)
335 ThreadID tid
= inst
->readTid();
336 Addr aligned_addr
= inst
->getMemAddr();
338 if (!cache_req
->is2ndSplit()) {
339 if (cache_req
->memReq
== NULL
) {
341 new Request(cpu
->asid
[tid
], aligned_addr
, acc_size
, flags
,
344 cpu
->readCpuId(), //@todo: use context id
348 assert(inst
->splitInst
);
350 if (inst
->splitMemReq
== NULL
) {
351 inst
->splitMemReq
= new Request(cpu
->asid
[tid
],
361 cache_req
->memReq
= inst
->splitMemReq
;
366 CacheUnit::doTLBAccess(DynInstPtr inst
, CacheReqPtr cache_req
, int acc_size
,
367 int flags
, TheISA::TLB::Mode tlb_mode
)
369 ThreadID tid
= inst
->readTid();
371 setupMemRequest(inst
, cache_req
, acc_size
, flags
);
373 //@todo: HACK: the DTB expects the correct PC in the ThreadContext
374 // but how if the memory accesses are speculative? Shouldn't
375 // we send along the requestor's PC to the translate functions?
376 ThreadContext
*tc
= cpu
->thread
[tid
]->getTC();
377 PCState old_pc
= tc
->pcState();
378 tc
->pcState() = inst
->pcState();
381 _tlb
->translateAtomic(cache_req
->memReq
, tc
, tlb_mode
);
382 tc
->pcState() = old_pc
;
384 if (inst
->fault
!= NoFault
) {
385 DPRINTF(InOrderTLB
, "[tid:%i]: %s encountered while translating "
386 "addr:%08p for [sn:%i].\n", tid
, inst
->fault
->name(),
387 cache_req
->memReq
->getVaddr(), inst
->seqNum
);
389 tlbBlocked
[tid
] = true;
390 tlbBlockSeqNum
[tid
] = inst
->seqNum
;
392 // Make sure nothing gets executed until after this faulting
393 // instruction gets handled.
394 inst
->setSerializeAfter();
396 // Mark it as complete so it can pass through next stage.
397 // Fault Handling will happen at commit/graduation
398 cache_req
->setCompleted();
400 DPRINTF(InOrderTLB
, "[tid:%i]: [sn:%i] virt. addr %08p translated "
401 "to phys. addr:%08p.\n", tid
, inst
->seqNum
,
402 cache_req
->memReq
->getVaddr(),
403 cache_req
->memReq
->getPaddr());
408 CacheUnit::trap(const Fault
&fault
, ThreadID tid
, DynInstPtr inst
)
410 tlbBlocked
[tid
] = false;
414 CacheUnit::read(DynInstPtr inst
, Addr addr
,
415 uint8_t *data
, unsigned size
, unsigned flags
)
417 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
418 assert(cache_req
&& "Can't Find Instruction for Read!");
420 // The block size of our peer
421 unsigned blockSize
= cacheBlkSize
;
423 //The size of the data we're trying to read.
425 inst
->totalSize
= size
;
427 if (inst
->traceData
) {
428 inst
->traceData
->setAddr(addr
);
431 if (inst
->split2ndAccess
) {
432 size
= inst
->split2ndSize
;
433 cache_req
->splitAccess
= true;
434 cache_req
->split2ndAccess
= true;
436 DPRINTF(InOrderCachePort
, "[sn:%i] Split Read Access (2 of 2) for "
437 "(%#x, %#x).\n", inst
->seqNum
, inst
->getMemAddr(),
442 //The address of the second part of this access if it needs to be split
443 //across a cache line boundary.
444 Addr secondAddr
= roundDown(addr
+ size
- 1, blockSize
);
447 if (secondAddr
> addr
&& !inst
->split2ndAccess
) {
449 if (!inst
->splitInst
) {
450 DPRINTF(InOrderCachePort
, "%i: sn[%i] Split Read Access (1 of 2) for "
451 "(%#x, %#x).\n", curTick(), inst
->seqNum
, addr
, secondAddr
);
453 unsigned stage_num
= cache_req
->getStageNum();
454 unsigned cmd
= inst
->curSkedEntry
->cmd
;
456 // 1. Make A New Inst. Schedule w/Split Read/Complete Entered on
458 // ==============================
459 // 2. Reassign curSkedPtr to current command (InitiateRead) on new
461 // ==============================
462 inst
->splitInst
= true;
463 inst
->setBackSked(cpu
->createBackEndSked(inst
));
464 inst
->curSkedEntry
= inst
->backSked
->find(stage_num
, cmd
);
466 DPRINTF(InOrderCachePort
, "[tid:%i] [sn:%i] Retrying Split Read "
467 "Access (1 of 2) for (%#x, %#x).\n", inst
->readTid(),
468 inst
->seqNum
, addr
, secondAddr
);
471 // Save All "Total" Split Information
472 // ==============================
473 inst
->splitMemData
= new uint8_t[size
];
475 // Split Information for First Access
476 // ==============================
477 size
= secondAddr
- addr
;
478 cache_req
->splitAccess
= true;
480 // Split Information for Second Access
481 // ==============================
482 inst
->split2ndSize
= addr
+ fullSize
- secondAddr
;
483 inst
->split2ndAddr
= secondAddr
;
484 inst
->split2ndDataPtr
= inst
->splitMemData
+ size
;
485 inst
->split2ndFlags
= flags
;
488 doTLBAccess(inst
, cache_req
, size
, flags
, TheISA::TLB::Read
);
490 if (inst
->fault
== NoFault
) {
491 if (!cache_req
->splitAccess
) {
492 cache_req
->reqData
= new uint8_t[size
];
493 doCacheAccess(inst
, NULL
);
495 if (!inst
->split2ndAccess
) {
496 cache_req
->reqData
= inst
->splitMemData
;
498 cache_req
->reqData
= inst
->split2ndDataPtr
;
501 doCacheAccess(inst
, NULL
, cache_req
);
509 CacheUnit::write(DynInstPtr inst
, uint8_t *data
, unsigned size
,
510 Addr addr
, unsigned flags
, uint64_t *write_res
)
512 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
513 assert(cache_req
&& "Can't Find Instruction for Write!");
515 // The block size of our peer
516 unsigned blockSize
= cacheBlkSize
;
518 //The size of the data we're trying to write.
520 inst
->totalSize
= size
;
522 if (inst
->traceData
) {
523 inst
->traceData
->setAddr(addr
);
526 if (inst
->split2ndAccess
) {
527 size
= inst
->split2ndSize
;
528 cache_req
->splitAccess
= true;
529 cache_req
->split2ndAccess
= true;
531 DPRINTF(InOrderCachePort
, "[sn:%i] Split Write Access (2 of 2) for "
532 "(%#x, %#x).\n", inst
->seqNum
, inst
->getMemAddr(),
536 //The address of the second part of this access if it needs to be split
537 //across a cache line boundary.
538 Addr secondAddr
= roundDown(addr
+ size
- 1, blockSize
);
540 if (secondAddr
> addr
&& !inst
->split2ndAccess
) {
542 DPRINTF(InOrderCachePort
, "[sn:%i] Split Write Access (1 of 2) for "
543 "(%#x, %#x).\n", inst
->seqNum
, addr
, secondAddr
);
545 // Save All "Total" Split Information
546 // ==============================
547 inst
->splitInst
= true;
549 if (!inst
->splitInstSked
) {
550 assert(0 && "Split Requests Not Supported for Now...");
552 // Schedule Split Read/Complete for Instruction
553 // ==============================
554 int stage_num
= cache_req
->getStageNum();
555 RSkedPtr inst_sked
= (stage_num
>= ThePipeline::BackEndStartStage
) ?
556 inst
->backSked
: inst
->frontSked
;
558 // this is just an arbitrarily high priority to ensure that this
559 // gets pushed to the back of the list
562 int isplit_cmd
= CacheUnit::InitSecondSplitWrite
;
564 ScheduleEntry(stage_num
,
566 cpu
->resPool
->getResIdx(DCache
),
570 int csplit_cmd
= CacheUnit::CompleteSecondSplitWrite
;
572 ScheduleEntry(stage_num
+ 1,
574 cpu
->resPool
->getResIdx(DCache
),
577 inst
->splitInstSked
= true;
579 DPRINTF(InOrderCachePort
, "[tid:%i] sn:%i] Retrying Split Read "
580 "Access (1 of 2) for (%#x, %#x).\n",
581 inst
->readTid(), inst
->seqNum
, addr
, secondAddr
);
586 // Split Information for First Access
587 // ==============================
588 size
= secondAddr
- addr
;
589 cache_req
->splitAccess
= true;
591 // Split Information for Second Access
592 // ==============================
593 inst
->split2ndSize
= addr
+ fullSize
- secondAddr
;
594 inst
->split2ndAddr
= secondAddr
;
595 inst
->split2ndFlags
= flags
;
596 inst
->splitInstSked
= true;
599 doTLBAccess(inst
, cache_req
, size
, flags
, TheISA::TLB::Write
);
601 if (inst
->fault
== NoFault
) {
602 if (!cache_req
->splitAccess
) {
603 cache_req
->reqData
= new uint8_t[size
];
604 memcpy(cache_req
->reqData
, data
, size
);
606 //inst->split2ndStoreDataPtr = cache_req->reqData;
607 //inst->split2ndStoreDataPtr += size;
609 doCacheAccess(inst
, write_res
);
611 doCacheAccess(inst
, write_res
, cache_req
);
621 CacheUnit::execute(int slot_num
)
623 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(reqs
[slot_num
]);
626 if (cachePortBlocked
&&
627 (cache_req
->cmd
== InitiateReadData
||
628 cache_req
->cmd
== InitiateWriteData
||
629 cache_req
->cmd
== InitSecondSplitRead
||
630 cache_req
->cmd
== InitSecondSplitWrite
)) {
631 DPRINTF(InOrderCachePort
, "Cache Port Blocked. Cannot Access\n");
632 cache_req
->done(false);
636 DynInstPtr inst
= cache_req
->inst
;
637 if (inst
->fault
!= NoFault
) {
638 DPRINTF(InOrderCachePort
,
639 "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
640 "next stage.\n", inst
->readTid(), inst
->seqNum
, inst
->fault
->name(),
642 finishCacheUnitReq(inst
, cache_req
);
646 if (inst
->isSquashed()) {
647 DPRINTF(InOrderCachePort
,
648 "[tid:%i]: [sn:%i]: Detected squashed instruction "
649 "next stage.\n", inst
->readTid(), inst
->seqNum
);
650 finishCacheUnitReq(inst
, cache_req
);
655 ThreadID tid
= inst
->readTid();
656 std::string acc_type
= "write";
659 switch (cache_req
->cmd
)
662 case InitiateReadData
:
666 case InitiateWriteData
:
667 if (cachePortBlocked
) {
668 DPRINTF(InOrderCachePort
, "Cache Port Blocked. Cannot Access\n");
669 cache_req
->done(false);
673 DPRINTF(InOrderCachePort
,
674 "[tid:%u]: [sn:%i] Initiating data %s access to %s for "
675 "addr. %08p\n", tid
, inst
->seqNum
, acc_type
, name(),
676 cache_req
->inst
->getMemAddr());
678 inst
->setCurResSlot(slot_num
);
680 if (inst
->isDataPrefetch() || inst
->isInstPrefetch()) {
688 case InitSecondSplitRead
:
689 DPRINTF(InOrderCachePort
,
690 "[tid:%u]: [sn:%i] Initiating split data read access to %s "
691 "for addr. %08p\n", tid
, inst
->seqNum
, name(),
692 cache_req
->inst
->split2ndAddr
);
693 inst
->split2ndAccess
= true;
694 assert(inst
->split2ndAddr
!= 0);
695 read(inst
, inst
->split2ndAddr
, &inst
->split2ndData
,
696 inst
->totalSize
, inst
->split2ndFlags
);
699 case InitSecondSplitWrite
:
700 DPRINTF(InOrderCachePort
,
701 "[tid:%u]: [sn:%i] Initiating split data write access to %s "
702 "for addr. %08p\n", tid
, inst
->seqNum
, name(),
703 cache_req
->inst
->getMemAddr());
705 inst
->split2ndAccess
= true;
706 assert(inst
->split2ndAddr
!= 0);
707 write(inst
, &inst
->split2ndData
, inst
->totalSize
,
708 inst
->split2ndAddr
, inst
->split2ndFlags
, NULL
);
711 case CompleteReadData
:
712 DPRINTF(InOrderCachePort
,
713 "[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n",
717 //@todo: timing translations need to check here...
718 assert(!inst
->isInstPrefetch() && "Can't Handle Inst. Prefecthes");
719 if (cache_req
->isMemAccComplete() || inst
->isDataPrefetch()) {
720 finishCacheUnitReq(inst
, cache_req
);
722 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
723 tid
, cache_req
->inst
->getMemAddr());
724 cache_req
->setCompleted(false);
725 cache_req
->setMemStall(true);
729 case CompleteWriteData
:
731 DPRINTF(InOrderCachePort
,
732 "[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n",
736 //@todo: check that timing translation is finished here
737 RequestPtr mem_req
= cache_req
->memReq
;
738 if (mem_req
->isCondSwap() || mem_req
->isLLSC() || mem_req
->isSwap()) {
739 DPRINTF(InOrderCachePort
, "Detected Conditional Store Inst.\n");
741 if (!cache_req
->isMemAccComplete()) {
742 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
743 tid
, cache_req
->inst
->getMemAddr());
744 cache_req
->setCompleted(false);
745 cache_req
->setMemStall(true);
748 DPRINTF(InOrderStall
, "Mem Acc Completed\n");
752 if (cache_req
->isMemAccPending()) {
753 DPRINTF(InOrderCachePort
, "Store Instruction Pending Completion.\n");
754 cache_req
->dataPkt
->reqData
= cache_req
->reqData
;
755 cache_req
->dataPkt
->memReq
= cache_req
->memReq
;
757 DPRINTF(InOrderCachePort
, "Store Instruction Finished Completion.\n");
759 //@todo: if split inst save data
760 finishCacheUnitReq(inst
, cache_req
);
764 case CompleteSecondSplitRead
:
765 DPRINTF(InOrderCachePort
,
766 "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read "
767 "Access\n", tid
, inst
->seqNum
);
769 //@todo: check that timing translation is finished here
770 assert(!inst
->isInstPrefetch() && "Can't Handle Inst. Prefecthes");
771 if (cache_req
->isMemAccComplete() || inst
->isDataPrefetch()) {
772 finishCacheUnitReq(inst
, cache_req
);
774 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
775 tid
, cache_req
->inst
->split2ndAddr
);
776 cache_req
->setCompleted(false);
777 cache_req
->setMemStall(true);
781 case CompleteSecondSplitWrite
:
782 DPRINTF(InOrderCachePort
,
783 "[tid:%i]: [sn:%i]: Trying to Complete Split Data Write "
784 "Access\n", tid
, inst
->seqNum
);
785 //@todo: illegal to have a unaligned cond.swap or llsc?
786 assert(!cache_req
->memReq
->isSwap() && !cache_req
->memReq
->isCondSwap()
787 && !cache_req
->memReq
->isLLSC());
789 if (cache_req
->isMemAccPending()) {
790 cache_req
->dataPkt
->reqData
= cache_req
->reqData
;
791 cache_req
->dataPkt
->memReq
= cache_req
->memReq
;
794 //@todo: check that timing translation is finished here
795 finishCacheUnitReq(inst
, cache_req
);
799 fatal("Unrecognized command to %s", resName
);
804 CacheUnit::finishCacheUnitReq(DynInstPtr inst
, CacheRequest
*cache_req
)
806 //@note: add back in for speculative load/store capability
807 //removeAddrDependency(inst);
808 cache_req
->setMemStall(false);
813 CacheUnit::buildDataPacket(CacheRequest
*cache_req
)
815 cache_req
->dataPkt
= new CacheReqPacket(cache_req
,
818 cache_req
->dataPkt
->refineCommand(); // handle LL/SC, etc.
820 DPRINTF(InOrderCachePort
, "[slot:%i]: Slot marked for %x\n",
821 cache_req
->getSlot(),
822 cache_req
->dataPkt
->getAddr());
824 cache_req
->dataPkt
->hasSlot
= true;
825 cache_req
->dataPkt
->dataStatic(cache_req
->reqData
);
829 CacheUnit::doCacheAccess(DynInstPtr inst
, uint64_t *write_res
,
830 CacheReqPtr split_req
)
832 Fault fault
= NoFault
;
834 ThreadID tid
= inst
->readTid();
836 bool do_access
= true; // flag to suppress cache access
838 // Special Handling if this is a split request
839 CacheReqPtr cache_req
;
840 if (split_req
== NULL
)
841 cache_req
= dynamic_cast<CacheReqPtr
>(reqs
[inst
->getCurResSlot()]);
843 cache_req
= split_req
;
847 // Make a new packet inside the CacheRequest object
849 buildDataPacket(cache_req
);
851 // Special Handling for LL/SC or Compare/Swap
852 bool is_write
= cache_req
->dataPkt
->isWrite();
853 RequestPtr mem_req
= cache_req
->dataPkt
->req
;
855 DPRINTF(InOrderCachePort
,
856 "[tid:%u]: [sn:%i]: Storing data: %s\n",
858 printMemData(cache_req
->dataPkt
->getPtr
<uint8_t>(),
859 cache_req
->dataPkt
->getSize()));
861 if (mem_req
->isCondSwap()) {
863 cache_req
->memReq
->setExtraData(*write_res
);
865 if (mem_req
->isLLSC()) {
866 assert(cache_req
->inst
->isStoreConditional());
867 DPRINTF(InOrderCachePort
, "Evaluating Store Conditional access\n");
868 do_access
= TheISA::handleLockedWrite(inst
.get(), mem_req
, cacheBlkSize
);
872 // Finally, go ahead and make the access if we can...
873 DPRINTF(InOrderCachePort
,
874 "[tid:%i] [sn:%i] attempting to access cache for addr %08p\n",
875 tid
, inst
->seqNum
, cache_req
->dataPkt
->getAddr());
878 if (!cachePort
->sendTimingReq(cache_req
->dataPkt
)) {
879 DPRINTF(InOrderCachePort
,
880 "[tid:%i] [sn:%i] cannot access cache, because port "
881 "is blocked. now waiting to retry request\n", tid
,
883 delete cache_req
->dataPkt
;
884 cache_req
->dataPkt
= NULL
;
886 delete cache_req
->memReq
;
887 cache_req
->memReq
= NULL
;
889 cache_req
->done(false);
890 cachePortBlocked
= true;
892 DPRINTF(InOrderCachePort
,
893 "[tid:%i] [sn:%i] is now waiting for cache response\n",
895 cache_req
->setCompleted();
896 cache_req
->setMemAccPending();
897 cachePortBlocked
= false;
899 } else if (mem_req
->isLLSC()){
900 // Store-Conditional instructions complete even if they "failed"
901 assert(cache_req
->inst
->isStoreConditional());
902 cache_req
->setCompleted(true);
905 "[tid:%i]: T%i Ignoring Failed Store Conditional Access\n",
908 processCacheCompletion(cache_req
->dataPkt
);
910 delete cache_req
->dataPkt
;
911 cache_req
->dataPkt
= NULL
;
913 delete cache_req
->memReq
;
914 cache_req
->memReq
= NULL
;
916 // Make cache request again since access due to
917 // inability to access
918 DPRINTF(InOrderStall
, "STALL: \n");
919 cache_req
->done(false);
925 CacheUnit::processSquash(CacheReqPacket
*cache_pkt
)
927 // The resource may no longer be actively servicing this
928 // packet. Scenarios like a store that has been sent to the
929 // memory system or access that's been squashed. If that's
930 // the case, we can't access the request slot because it
931 // will be either invalid or servicing another request.
932 if (!cache_pkt
->hasSlot
) {
933 DPRINTF(InOrderCachePort
,
934 "%x does not have a slot in unit, ignoring.\n",
935 cache_pkt
->getAddr());
937 if (cache_pkt
->reqData
) {
938 delete [] cache_pkt
->reqData
;
939 cache_pkt
->reqData
= NULL
;
942 if (cache_pkt
->memReq
) {
943 delete cache_pkt
->memReq
;
944 cache_pkt
->memReq
= NULL
;
952 DPRINTF(InOrderCachePort
, "%x has slot %i\n",
953 cache_pkt
->getAddr(), cache_pkt
->cacheReq
->getSlot());
957 // It's possible that the request is squashed but the
958 // packet is still acknowledged by the resource. Squashes
959 // should happen at the end of the cycles and trigger the
960 // code above, but if not, this would handle any timing
961 // variations due to diff. user parameters.
962 if (cache_pkt
->cacheReq
->isSquashed()) {
963 DPRINTF(InOrderCachePort
,
964 "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n",
965 cache_pkt
->cacheReq
->getInst()->readTid(),
966 cache_pkt
->cacheReq
->getInst()->seqNum
);
968 cache_pkt
->cacheReq
->setMemAccPending(false);
969 cache_pkt
->cacheReq
->freeSlot();
981 CacheUnit::processCacheCompletion(PacketPtr pkt
)
983 //@todo: use packet sender state instead of deriving from packet class to
985 CacheReqPacket
* cache_pkt
= dynamic_cast<CacheReqPacket
*>(pkt
);
988 DPRINTF(InOrderCachePort
, "Finished request for %x\n", pkt
->getAddr());
990 if (processSquash(cache_pkt
))
993 CacheRequest
*cache_req
= dynamic_cast<CacheReqPtr
>(
994 findRequest(cache_pkt
->cacheReq
->getInst(), cache_pkt
->instIdx
));
997 panic("[tid:%u]: [sn:%i]: Can't find slot for cache access to "
998 "addr. %08p\n", cache_pkt
->cacheReq
->getInst()->readTid(),
999 cache_pkt
->cacheReq
->getInst()->seqNum
,
1000 cache_pkt
->cacheReq
->getInst()->getMemAddr());
1004 assert(cache_req
== cache_pkt
->cacheReq
);
1006 DPRINTF(InOrderCachePort
,
1007 "[tid:%u]: [sn:%i]: [slot:%i] Waking from cache access (vaddr.%08p, paddr:%08p)\n",
1008 cache_pkt
->cacheReq
->getInst()->readTid(),
1009 cache_pkt
->cacheReq
->getInst()->seqNum
,
1010 cache_req
->getSlot(),
1011 cache_pkt
->req
->getVaddr(),
1012 cache_pkt
->req
->getPaddr());
1014 // Get resource request info
1015 unsigned stage_num
= cache_req
->getStageNum();
1016 DynInstPtr inst
= cache_req
->inst
;
1017 ThreadID tid
= cache_req
->inst
->readTid();
1019 assert(!cache_req
->isSquashed());
1020 assert(inst
->staticInst
&& inst
->isMemRef());
1023 DPRINTF(InOrderCachePort
,
1024 "[tid:%u]: [sn:%i]: Processing cache access\n",
1027 PacketPtr split_pkt
= NULL
;
1028 if (inst
->splitInst
) {
1029 inst
->splitFinishCnt
++;
1031 if (inst
->splitFinishCnt
== 2) {
1032 cache_req
->memReq
->setVirt(0/*inst->tid*/,
1036 cpu
->dataMasterId(),
1039 split_pkt
= new Packet(cache_req
->memReq
, cache_req
->pktCmd
);
1040 split_pkt
->dataStatic(inst
->splitMemData
);
1042 DPRINTF(InOrderCachePort
, "Completing Split Access.\n");
1043 inst
->completeAcc(split_pkt
);
1046 inst
->completeAcc(cache_pkt
);
1049 inst
->setExecuted();
1051 if (inst
->isLoad()) {
1052 assert(cache_pkt
->isRead());
1054 if (cache_pkt
->req
->isLLSC()) {
1055 DPRINTF(InOrderCachePort
,
1056 "[tid:%u]: Handling Load-Linked for [sn:%u]\n",
1058 TheISA::handleLockedRead(inst
.get(), cache_pkt
->req
);
1061 DPRINTF(InOrderCachePort
,
1062 "[tid:%u]: [sn:%i]: Bytes loaded were: %s\n",
1064 (split_pkt
) ? printMemData(split_pkt
->getPtr
<uint8_t>(),
1065 split_pkt
->getSize()) :
1066 printMemData(cache_pkt
->getPtr
<uint8_t>(),
1067 cache_pkt
->getSize()));
1068 } else if(inst
->isStore()) {
1069 assert(cache_pkt
->isWrite());
1071 DPRINTF(InOrderCachePort
,
1072 "[tid:%u]: [sn:%i]: Bytes stored were: %s\n",
1074 (split_pkt
) ? printMemData(split_pkt
->getPtr
<uint8_t>(),
1075 split_pkt
->getSize()) :
1076 printMemData(cache_pkt
->getPtr
<uint8_t>(),
1077 cache_pkt
->getSize()));
1086 cache_req
->setMemAccPending(false);
1087 cache_req
->setMemAccCompleted();
1089 if (cache_req
->isMemStall() &&
1090 cpu
->threadModel
== InOrderCPU::SwitchOnCacheMiss
) {
1091 DPRINTF(InOrderCachePort
, "[tid:%u] Waking up from Cache Miss.\n",
1094 cpu
->activateContext(tid
);
1096 DPRINTF(ThreadModel
, "Activating [tid:%i] after return from cache"
1100 // Wake up the CPU (if it went to sleep and was waiting on this
1101 // completion event).
1104 DPRINTF(Activity
, "[tid:%u] Activating %s due to cache completion\n",
1105 tid
, cpu
->pipelineStage
[stage_num
]->name());
1107 cpu
->switchToActive(stage_num
);
1111 CacheUnit::recvRetry()
1113 DPRINTF(InOrderCachePort
, "Unblocking Cache Port. \n");
1115 assert(cachePortBlocked
);
1117 // Clear the cache port for use again
1118 cachePortBlocked
= false;
1123 CacheUnitEvent::CacheUnitEvent()
1128 CacheUnitEvent::process()
1130 DynInstPtr inst
= resource
->reqs
[slotIdx
]->inst
;
1131 int stage_num
= resource
->reqs
[slotIdx
]->getStageNum();
1132 ThreadID tid
= inst
->threadNumber
;
1133 CacheReqPtr req_ptr
= dynamic_cast<CacheReqPtr
>(resource
->reqs
[slotIdx
]);
1135 DPRINTF(InOrderTLB
, "Waking up from TLB Miss caused by [sn:%i].\n",
1138 CacheUnit
* tlb_res
= dynamic_cast<CacheUnit
*>(resource
);
1141 //@todo: eventually, we should do a timing translation w/
1142 // hw page table walk on tlb miss
1143 DPRINTF(InOrderTLB
, "Handling Fault %s : [sn:%i] %x\n", inst
->fault
->name(), inst
->seqNum
, inst
->getMemAddr());
1144 inst
->fault
->invoke(tlb_res
->cpu
->tcBase(tid
), inst
->staticInst
);
1146 tlb_res
->tlbBlocked
[tid
] = false;
1148 tlb_res
->cpu
->pipelineStage
[stage_num
]->
1149 unsetResStall(tlb_res
->reqs
[slotIdx
], tid
);
1151 req_ptr
->tlbStall
= false;
1153 //@todo: timing translation needs to have some type of independent
1154 // info regarding if it's squashed or not so we can
1155 // free up the resource if a request gets squashed in the middle
1157 if (req_ptr
->isSquashed()) {
1158 req_ptr
->freeSlot();
1161 tlb_res
->cpu
->wakeCPU();
1165 CacheUnit::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
1166 InstSeqNum squash_seq_num
, ThreadID tid
)
1168 // If squashing due to memory stall, then we do NOT want to
1169 // squash the instruction that caused the stall so we
1170 // increment the sequence number here to prevent that.
1172 // NOTE: This is only for the SwitchOnCacheMiss Model
1173 // NOTE: If you have multiple outstanding misses from the same
1174 // thread then you need to reevaluate this code
1175 // NOTE: squash should originate from
1176 // pipeline_stage.cc:processInstSchedule
1177 DPRINTF(InOrderCachePort
, "Squashing above [sn:%u]\n",
1178 squash_seq_num
+ 1);
1180 squash(inst
, stage_num
, squash_seq_num
+ 1, tid
);
1184 CacheUnit::squashCacheRequest(CacheReqPtr req_ptr
)
1186 DynInstPtr inst
= req_ptr
->getInst();
1187 req_ptr
->setSquashed();
1188 inst
->setSquashed();
1190 //@note: add back in for speculative load/store capability
1191 /*if (inst->validMemAddr()) {
1192 DPRINTF(AddrDep, "Squash of [tid:%i] [sn:%i], attempting to "
1193 "remove addr. %08p dependencies.\n",
1196 inst->getMemAddr());
1198 removeAddrDependency(inst);
1204 CacheUnit::squash(DynInstPtr inst
, int stage_num
,
1205 InstSeqNum squash_seq_num
, ThreadID tid
)
1207 if (tlbBlocked
[tid
] &&
1208 tlbBlockSeqNum
[tid
] > squash_seq_num
) {
1209 DPRINTF(InOrderCachePort
, "Releasing TLB Block due to "
1210 " squash after [sn:%i].\n", squash_seq_num
);
1211 tlbBlocked
[tid
] = false;
1214 for (int i
= 0; i
< width
; i
++) {
1215 ResReqPtr req_ptr
= reqs
[i
];
1217 if (req_ptr
->valid
&&
1218 req_ptr
->getInst()->readTid() == tid
&&
1219 req_ptr
->getInst()->seqNum
> squash_seq_num
) {
1221 DPRINTF(InOrderCachePort
,
1222 "[tid:%i] Squashing request from [sn:%i]\n",
1223 req_ptr
->getInst()->readTid(), req_ptr
->getInst()->seqNum
);
1225 if (req_ptr
->isSquashed()) {
1226 DPRINTF(AddrDep
, "Request for [tid:%i] [sn:%i] already "
1227 "squashed, ignoring squash process.\n",
1228 req_ptr
->getInst()->readTid(),
1229 req_ptr
->getInst()->seqNum
);
1233 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(req_ptr
);
1236 squashCacheRequest(cache_req
);
1238 int req_slot_num
= req_ptr
->getSlot();
1240 if (cache_req
->tlbStall
) {
1241 tlbBlocked
[tid
] = false;
1243 int stall_stage
= reqs
[req_slot_num
]->getStageNum();
1245 cpu
->pipelineStage
[stall_stage
]->
1246 unsetResStall(reqs
[req_slot_num
], tid
);
1249 if (cache_req
->isMemAccPending()) {
1250 cache_req
->dataPkt
->reqData
= cache_req
->reqData
;
1251 cache_req
->dataPkt
->memReq
= cache_req
->memReq
;
1254 if (!cache_req
->tlbStall
)
1255 freeSlot(req_slot_num
);
1262 CacheRequest::clearRequest()
1264 if (!memAccPending
) {
1265 if (reqData
&& !splitAccess
)
1275 dataPkt
->hasSlot
= false;
1281 memAccComplete
= false;
1282 memAccPending
= false;
1284 splitAccess
= false;
1285 splitAccessNum
= -1;
1286 split2ndAccess
= false;
1288 fetchBufferFill
= false;
1290 ResourceRequest::clearRequest();