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 "cpu/inorder/resource_pool.hh"
44 #include "mem/request.hh"
47 using namespace TheISA
;
48 using namespace ThePipeline
;
51 CacheUnit::CachePort::recvAtomic(PacketPtr pkt
)
53 panic("CacheUnit::CachePort doesn't expect recvAtomic callback!");
58 CacheUnit::CachePort::recvFunctional(PacketPtr pkt
)
60 panic("CacheUnit::CachePort doesn't expect recvFunctional callback!");
64 CacheUnit::CachePort::recvStatusChange(Status status
)
66 if (status
== RangeChange
)
69 panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
73 CacheUnit::CachePort::recvTiming(Packet
*pkt
)
75 cachePortUnit
->processCacheCompletion(pkt
);
80 CacheUnit::CachePort::recvRetry()
82 cachePortUnit
->recvRetry();
85 CacheUnit::CacheUnit(string res_name
, int res_id
, int res_width
,
86 int res_latency
, InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
87 : Resource(res_name
, res_id
, res_width
, res_latency
, _cpu
),
88 cachePortBlocked(false), predecoder(NULL
)
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 // For a Split-Load, the instruction would have processed once already
141 // causing the address to be unset.
142 if (!inst
->validMemAddr() && !inst
->splitInst
) {
143 panic("Mem. Addr. must be set before requesting cache access\n");
146 Addr req_addr
= inst
->getMemAddr();
148 if (resName
== "icache_port" ||
149 find(addrList
[tid
].begin(), addrList
[tid
].end(), req_addr
) ==
150 addrList
[tid
].end()) {
152 int new_slot
= Resource::getSlot(inst
);
157 inst
->memTime
= curTick
;
158 addrList
[tid
].push_back(req_addr
);
159 addrMap
[tid
][req_addr
] = inst
->seqNum
;
160 DPRINTF(InOrderCachePort
,
161 "[tid:%i]: [sn:%i]: Address %08p added to dependency list\n",
162 inst
->readTid(), inst
->seqNum
, req_addr
);
165 // Allow same instruction multiple accesses to same address
166 if (addrMap
[tid
][req_addr
] == inst
->seqNum
) {
167 int new_slot
= Resource::getSlot(inst
);
174 DPRINTF(InOrderCachePort
,
175 "[tid:%i] Denying request because there is an outstanding"
176 " request to/for addr. %08p. by [sn:%i] @ tick %i\n",
177 inst
->readTid(), req_addr
, addrMap
[tid
][req_addr
], inst
->memTime
);
186 CacheUnit::freeSlot(int slot_num
)
188 ThreadID tid
= reqMap
[slot_num
]->inst
->readTid();
190 vector
<Addr
>::iterator vect_it
=
191 find(addrList
[tid
].begin(), addrList
[tid
].end(),
192 reqMap
[slot_num
]->inst
->getMemAddr());
194 assert(vect_it
!= addrList
[tid
].end() ||
195 reqMap
[slot_num
]->inst
->splitInst
);
197 DPRINTF(InOrderCachePort
,
198 "[tid:%i]: Address %08p removed from dependency list\n",
199 reqMap
[slot_num
]->inst
->readTid(), (*vect_it
));
201 if (vect_it
!= addrList
[tid
].end()) {
203 DPRINTF(InOrderCachePort
,
204 "[tid:%i]: Address %08p removed from dependency list\n",
205 reqMap
[slot_num
]->inst
->readTid(), (*vect_it
));
207 addrList
[tid
].erase(vect_it
);
210 Resource::freeSlot(slot_num
);
214 CacheUnit::findRequest(DynInstPtr inst
)
216 map
<int, ResReqPtr
>::iterator map_it
= reqMap
.begin();
217 map
<int, ResReqPtr
>::iterator map_end
= reqMap
.end();
219 while (map_it
!= map_end
) {
220 CacheRequest
* cache_req
= dynamic_cast<CacheRequest
*>((*map_it
).second
);
224 cache_req
->getInst() == inst
&&
225 cache_req
->instIdx
== inst
->resSched
.top()->idx
) {
235 CacheUnit::findSplitRequest(DynInstPtr inst
, int idx
)
237 map
<int, ResReqPtr
>::iterator map_it
= reqMap
.begin();
238 map
<int, ResReqPtr
>::iterator map_end
= reqMap
.end();
240 while (map_it
!= map_end
) {
241 CacheRequest
* cache_req
= dynamic_cast<CacheRequest
*>((*map_it
).second
);
245 cache_req
->getInst() == inst
&&
246 cache_req
->instIdx
== idx
) {
257 CacheUnit::getRequest(DynInstPtr inst
, int stage_num
, int res_idx
,
258 int slot_num
, unsigned cmd
)
260 ScheduleEntry
* sched_entry
= inst
->resSched
.top();
262 if (!inst
->validMemAddr()) {
263 panic("Mem. Addr. must be set before requesting cache access\n");
266 MemCmd::Command pkt_cmd
;
268 switch (sched_entry
->cmd
)
270 case InitSecondSplitRead
:
271 pkt_cmd
= MemCmd::ReadReq
;
273 DPRINTF(InOrderCachePort
,
274 "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
275 inst
->readTid(), inst
->seqNum
, inst
->split2ndAddr
);
278 case InitiateReadData
:
279 pkt_cmd
= MemCmd::ReadReq
;
281 DPRINTF(InOrderCachePort
,
282 "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
283 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
286 case InitSecondSplitWrite
:
287 pkt_cmd
= MemCmd::WriteReq
;
289 DPRINTF(InOrderCachePort
,
290 "[tid:%i]: Write request from [sn:%i] for addr %08p\n",
291 inst
->readTid(), inst
->seqNum
, inst
->split2ndAddr
);
294 case InitiateWriteData
:
295 pkt_cmd
= MemCmd::WriteReq
;
297 DPRINTF(InOrderCachePort
,
298 "[tid:%i]: Write request from [sn:%i] for addr %08p\n",
299 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
303 pkt_cmd
= MemCmd::ReadReq
;
305 DPRINTF(InOrderCachePort
,
306 "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
307 inst
->readTid(), inst
->seqNum
, inst
->getMemAddr());
311 panic("%i: Unexpected request type (%i) to %s", curTick
,
312 sched_entry
->cmd
, name());
315 return new CacheRequest(this, inst
, stage_num
, id
, slot_num
,
316 sched_entry
->cmd
, 0, pkt_cmd
,
317 0/*flags*/, this->cpu
->readCpuId(),
318 inst
->resSched
.top()->idx
);
322 CacheUnit::requestAgain(DynInstPtr inst
, bool &service_request
)
324 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
327 // Check to see if this instruction is requesting the same command
328 // or a different one
329 if (cache_req
->cmd
!= inst
->resSched
.top()->cmd
&&
330 cache_req
->instIdx
== inst
->resSched
.top()->idx
) {
331 // If different, then update command in the request
332 cache_req
->cmd
= inst
->resSched
.top()->cmd
;
333 DPRINTF(InOrderCachePort
,
334 "[tid:%i]: [sn:%i]: Updating the command for this "
335 "instruction\n ", inst
->readTid(), inst
->seqNum
);
337 service_request
= true;
338 } else if (inst
->resSched
.top()->idx
!= CacheUnit::InitSecondSplitRead
&&
339 inst
->resSched
.top()->idx
!= CacheUnit::InitSecondSplitWrite
) {
340 // If same command, just check to see if memory access was completed
341 // but dont try to re-execute
342 DPRINTF(InOrderCachePort
,
343 "[tid:%i]: [sn:%i]: requesting this resource again\n",
344 inst
->readTid(), inst
->seqNum
);
346 service_request
= true;
351 CacheUnit::doTLBAccess(DynInstPtr inst
, CacheReqPtr cache_req
, int acc_size
,
352 int flags
, TheISA::TLB::Mode tlb_mode
)
354 ThreadID tid
= inst
->readTid();
355 Addr aligned_addr
= inst
->getMemAddr();
356 unsigned stage_num
= cache_req
->getStageNum();
357 unsigned slot_idx
= cache_req
->getSlot();
359 if (tlb_mode
== TheISA::TLB::Execute
) {
360 inst
->fetchMemReq
= new Request(inst
->readTid(), aligned_addr
,
361 acc_size
, flags
, inst
->readPC(),
362 cpu
->readCpuId(), inst
->readTid());
363 cache_req
->memReq
= inst
->fetchMemReq
;
365 if (!cache_req
->is2ndSplit()) {
366 inst
->dataMemReq
= new Request(cpu
->asid
[tid
], aligned_addr
,
367 acc_size
, flags
, inst
->readPC(),
368 cpu
->readCpuId(), inst
->readTid());
369 cache_req
->memReq
= inst
->dataMemReq
;
371 assert(inst
->splitInst
);
373 inst
->splitMemReq
= new Request(cpu
->asid
[tid
],
380 cache_req
->memReq
= inst
->splitMemReq
;
386 _tlb
->translateAtomic(cache_req
->memReq
,
387 cpu
->thread
[tid
]->getTC(), tlb_mode
);
389 if (cache_req
->fault
!= NoFault
) {
390 DPRINTF(InOrderTLB
, "[tid:%i]: %s encountered while translating "
391 "addr:%08p for [sn:%i].\n", tid
, cache_req
->fault
->name(),
392 cache_req
->memReq
->getVaddr(), inst
->seqNum
);
394 cpu
->pipelineStage
[stage_num
]->setResStall(cache_req
, tid
);
396 tlbBlocked
[tid
] = true;
398 cache_req
->tlbStall
= true;
400 scheduleEvent(slot_idx
, 1);
402 cpu
->trap(cache_req
->fault
, tid
);
404 DPRINTF(InOrderTLB
, "[tid:%i]: [sn:%i] virt. addr %08p translated "
405 "to phys. addr:%08p.\n", tid
, inst
->seqNum
,
406 cache_req
->memReq
->getVaddr(),
407 cache_req
->memReq
->getPaddr());
410 return cache_req
->fault
;
415 CacheUnit::read(DynInstPtr inst
, Addr addr
, T
&data
, 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
= this->cachePort
->peerBlockSize();
423 //The size of the data we're trying to read.
424 int dataSize
= sizeof(T
);
426 if (inst
->split2ndAccess
) {
427 dataSize
= inst
->split2ndSize
;
428 cache_req
->splitAccess
= true;
429 cache_req
->split2ndAccess
= true;
431 DPRINTF(InOrderCachePort
, "%i: sn[%i] Split Read Access (2 of 2) for (%#x, %#x).\n", curTick
, inst
->seqNum
,
432 inst
->getMemAddr(), inst
->split2ndAddr
);
436 //The address of the second part of this access if it needs to be split
437 //across a cache line boundary.
438 Addr secondAddr
= roundDown(addr
+ dataSize
- 1, blockSize
);
441 if (secondAddr
> addr
&& !inst
->split2ndAccess
) {
442 DPRINTF(InOrderCachePort
, "%i: sn[%i] Split Read Access (1 of 2) for (%#x, %#x).\n", curTick
, inst
->seqNum
,
445 // Save All "Total" Split Information
446 // ==============================
447 inst
->splitInst
= true;
448 inst
->splitMemData
= new uint8_t[dataSize
];
449 inst
->splitTotalSize
= dataSize
;
452 // Schedule Split Read/Complete for Instruction
453 // ==============================
454 int stage_num
= cache_req
->getStageNum();
456 int stage_pri
= ThePipeline::getNextPriority(inst
, stage_num
);
458 inst
->resSched
.push(new ScheduleEntry(stage_num
,
460 cpu
->resPool
->getResIdx(DCache
),
461 CacheUnit::InitSecondSplitRead
,
465 inst
->resSched
.push(new ScheduleEntry(stage_num
+ 1,
467 cpu
->resPool
->getResIdx(DCache
),
468 CacheUnit::CompleteSecondSplitRead
,
473 // Split Information for First Access
474 // ==============================
475 dataSize
= secondAddr
- addr
;
476 cache_req
->splitAccess
= true;
478 // Split Information for Second Access
479 // ==============================
480 inst
->split2ndSize
= addr
+ sizeof(T
) - secondAddr
;
481 inst
->split2ndAddr
= secondAddr
;
482 inst
->split2ndDataPtr
= inst
->splitMemData
+ dataSize
;
483 inst
->split2ndFlags
= flags
;
486 doTLBAccess(inst
, cache_req
, dataSize
, flags
, TheISA::TLB::Read
);
488 if (cache_req
->fault
== NoFault
) {
489 if (!cache_req
->splitAccess
) {
490 cache_req
->reqData
= new uint8_t[dataSize
];
491 doCacheAccess(inst
, NULL
);
493 if (!inst
->split2ndAccess
) {
494 cache_req
->reqData
= inst
->splitMemData
;
496 cache_req
->reqData
= inst
->split2ndDataPtr
;
499 doCacheAccess(inst
, NULL
, cache_req
);
503 return cache_req
->fault
;
508 CacheUnit::write(DynInstPtr inst
, T data
, Addr addr
, unsigned flags
,
511 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(findRequest(inst
));
512 assert(cache_req
&& "Can't Find Instruction for Write!");
514 // The block size of our peer
515 unsigned blockSize
= this->cachePort
->peerBlockSize();
517 //The size of the data we're trying to read.
518 int dataSize
= sizeof(T
);
520 if (inst
->split2ndAccess
) {
521 dataSize
= inst
->split2ndSize
;
522 cache_req
->splitAccess
= true;
523 cache_req
->split2ndAccess
= true;
525 DPRINTF(InOrderCachePort
, "%i: sn[%i] Split Write Access (2 of 2) for (%#x, %#x).\n", curTick
, inst
->seqNum
,
526 inst
->getMemAddr(), inst
->split2ndAddr
);
529 //The address of the second part of this access if it needs to be split
530 //across a cache line boundary.
531 Addr secondAddr
= roundDown(addr
+ dataSize
- 1, blockSize
);
533 if (secondAddr
> addr
&& !inst
->split2ndAccess
) {
534 DPRINTF(InOrderCachePort
, "%i: sn[%i] Split Write Access (1 of 2) for (%#x, %#x).\n", curTick
, inst
->seqNum
,
537 // Save All "Total" Split Information
538 // ==============================
539 inst
->splitInst
= true;
540 inst
->splitTotalSize
= dataSize
;
542 // Schedule Split Read/Complete for Instruction
543 // ==============================
544 int stage_num
= cache_req
->getStageNum();
546 int stage_pri
= ThePipeline::getNextPriority(inst
, stage_num
);
548 inst
->resSched
.push(new ScheduleEntry(stage_num
,
550 cpu
->resPool
->getResIdx(DCache
),
551 CacheUnit::InitSecondSplitWrite
,
555 inst
->resSched
.push(new ScheduleEntry(stage_num
+ 1,
557 cpu
->resPool
->getResIdx(DCache
),
558 CacheUnit::CompleteSecondSplitWrite
,
562 // Split Information for First Access
563 // ==============================
564 dataSize
= secondAddr
- addr
;
565 cache_req
->splitAccess
= true;
567 // Split Information for Second Access
568 // ==============================
569 inst
->split2ndSize
= addr
+ sizeof(T
) - secondAddr
;
570 inst
->split2ndAddr
= secondAddr
;
571 inst
->split2ndStoreDataPtr
= &cache_req
->inst
->storeData
;
572 inst
->split2ndStoreDataPtr
+= dataSize
;
573 inst
->split2ndFlags
= flags
;
576 doTLBAccess(inst
, cache_req
, dataSize
, flags
, TheISA::TLB::Write
);
578 if (cache_req
->fault
== NoFault
) {
579 if (!cache_req
->splitAccess
) {
580 // Remove this line since storeData is saved in INST?
581 cache_req
->reqData
= new uint8_t[dataSize
];
582 doCacheAccess(inst
, write_res
);
584 doCacheAccess(inst
, write_res
, cache_req
);
589 return cache_req
->fault
;
594 CacheUnit::execute(int slot_num
)
596 if (cachePortBlocked
) {
597 DPRINTF(InOrderCachePort
, "Cache Port Blocked. Cannot Access\n");
601 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(reqMap
[slot_num
]);
604 DynInstPtr inst
= cache_req
->inst
;
606 ThreadID tid
= inst
->readTid();
607 int seq_num
= inst
->seqNum
;
608 std::string acc_type
= "write";
612 cache_req
->fault
= NoFault
;
614 switch (cache_req
->cmd
)
618 //@TODO: Switch to size of full cache block. Store in fetch buffer
619 int acc_size
= sizeof(TheISA::MachInst
);
621 doTLBAccess(inst
, cache_req
, acc_size
, 0, TheISA::TLB::Execute
);
623 // Only Do Access if no fault from TLB
624 if (cache_req
->fault
== NoFault
) {
626 DPRINTF(InOrderCachePort
,
627 "[tid:%u]: Initiating fetch access to %s for addr. %08p\n",
628 tid
, name(), cache_req
->inst
->getMemAddr());
630 cache_req
->reqData
= new uint8_t[acc_size
];
632 inst
->setCurResSlot(slot_num
);
640 case InitiateReadData
:
644 case InitiateWriteData
:
646 DPRINTF(InOrderCachePort
,
647 "[tid:%u]: [sn:%i] Initiating data %s access to %s for addr. %08p\n",
648 tid
, inst
->seqNum
, acc_type
, name(), cache_req
->inst
->getMemAddr());
650 inst
->setCurResSlot(slot_num
);
652 if (inst
->isDataPrefetch() || inst
->isInstPrefetch()) {
660 case InitSecondSplitRead
:
661 DPRINTF(InOrderCachePort
,
662 "[tid:%u]: [sn:%i] Initiating split data read access to %s for addr. %08p\n",
663 tid
, inst
->seqNum
, name(), cache_req
->inst
->split2ndAddr
);
664 inst
->split2ndAccess
= true;
665 assert(inst
->split2ndAddr
!= 0);
666 read(inst
, inst
->split2ndAddr
, inst
->split2ndData
, inst
->split2ndFlags
);
669 case InitSecondSplitWrite
:
670 DPRINTF(InOrderCachePort
,
671 "[tid:%u]: [sn:%i] Initiating split data write access to %s for addr. %08p\n",
672 tid
, inst
->seqNum
, name(), cache_req
->inst
->getMemAddr());
674 inst
->split2ndAccess
= true;
675 assert(inst
->split2ndAddr
!= 0);
676 write(inst
, inst
->split2ndAddr
, inst
->split2ndData
, inst
->split2ndFlags
, NULL
);
681 if (cache_req
->isMemAccComplete()) {
682 DPRINTF(InOrderCachePort
,
683 "[tid:%i]: Completing Fetch Access for [sn:%i]\n",
687 DPRINTF(InOrderCachePort
, "[tid:%i]: Instruction [sn:%i] is: %s\n",
688 tid
, seq_num
, inst
->staticInst
->disassemble(inst
->PC
));
690 delete cache_req
->dataPkt
;
691 //cache_req->setMemStall(false);
694 DPRINTF(InOrderCachePort
,
695 "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
697 DPRINTF(InOrderStall
,
698 "STALL: [tid:%i]: Fetch miss from %08p\n",
699 tid
, cache_req
->inst
->readPC());
700 cache_req
->setCompleted(false);
701 //cache_req->setMemStall(true);
705 case CompleteReadData
:
706 case CompleteWriteData
:
707 DPRINTF(InOrderCachePort
,
708 "[tid:%i]: [sn:%i]: Trying to Complete Data Access\n",
711 if (cache_req
->isMemAccComplete() ||
712 inst
->isDataPrefetch() ||
713 inst
->isInstPrefetch()) {
714 cache_req
->setMemStall(false);
717 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
718 tid
, cache_req
->inst
->getMemAddr());
719 cache_req
->setCompleted(false);
720 cache_req
->setMemStall(true);
724 case CompleteSecondSplitRead
:
725 DPRINTF(InOrderCachePort
,
726 "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read Access\n",
729 if (cache_req
->isMemAccComplete() ||
730 inst
->isDataPrefetch() ||
731 inst
->isInstPrefetch()) {
732 cache_req
->setMemStall(false);
735 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
736 tid
, cache_req
->inst
->split2ndAddr
);
737 cache_req
->setCompleted(false);
738 cache_req
->setMemStall(true);
742 case CompleteSecondSplitWrite
:
743 DPRINTF(InOrderCachePort
,
744 "[tid:%i]: [sn:%i]: Trying to Complete Split Data Write Access\n",
747 if (cache_req
->isMemAccComplete() ||
748 inst
->isDataPrefetch() ||
749 inst
->isInstPrefetch()) {
750 cache_req
->setMemStall(false);
753 DPRINTF(InOrderStall
, "STALL: [tid:%i]: Data miss from %08p\n",
754 tid
, cache_req
->inst
->split2ndAddr
);
755 cache_req
->setCompleted(false);
756 cache_req
->setMemStall(true);
761 fatal("Unrecognized command to %s", resName
);
766 CacheUnit::prefetch(DynInstPtr inst
)
768 warn_once("Prefetching currently unimplemented");
770 CacheReqPtr cache_req
771 = dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
774 // Clean-Up cache resource request so
775 // other memory insts. can use them
776 cache_req
->setCompleted();
777 cachePortBlocked
= false;
778 cache_req
->setMemAccPending(false);
779 cache_req
->setMemAccCompleted();
780 inst
->unsetMemAddr();
785 CacheUnit::writeHint(DynInstPtr inst
)
787 warn_once("Write Hints currently unimplemented");
789 CacheReqPtr cache_req
790 = dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
793 // Clean-Up cache resource request so
794 // other memory insts. can use them
795 cache_req
->setCompleted();
796 cachePortBlocked
= false;
797 cache_req
->setMemAccPending(false);
798 cache_req
->setMemAccCompleted();
799 inst
->unsetMemAddr();
802 // @TODO: Split into doCacheRead() and doCacheWrite()
804 CacheUnit::doCacheAccess(DynInstPtr inst
, uint64_t *write_res
, CacheReqPtr split_req
)
806 Fault fault
= NoFault
;
808 ThreadID tid
= inst
->readTid();
811 CacheReqPtr cache_req
;
813 if (split_req
== NULL
) {
814 cache_req
= dynamic_cast<CacheReqPtr
>(reqMap
[inst
->getCurResSlot()]);
816 cache_req
= split_req
;
821 // Check for LL/SC and if so change command
822 if (cache_req
->memReq
->isLLSC() && cache_req
->pktCmd
== MemCmd::ReadReq
) {
823 cache_req
->pktCmd
= MemCmd::LoadLockedReq
;
826 if (cache_req
->pktCmd
== MemCmd::WriteReq
) {
828 cache_req
->memReq
->isSwap() ? MemCmd::SwapReq
:
829 (cache_req
->memReq
->isLLSC() ? MemCmd::StoreCondReq
833 cache_req
->dataPkt
= new CacheReqPacket(cache_req
, cache_req
->pktCmd
,
834 Packet::Broadcast
, cache_req
->instIdx
);
836 if (cache_req
->dataPkt
->isRead()) {
837 cache_req
->dataPkt
->dataStatic(cache_req
->reqData
);
838 } else if (cache_req
->dataPkt
->isWrite()) {
839 if (inst
->split2ndAccess
) {
840 cache_req
->dataPkt
->dataStatic(inst
->split2ndStoreDataPtr
);
842 cache_req
->dataPkt
->dataStatic(&cache_req
->inst
->storeData
);
845 if (cache_req
->memReq
->isCondSwap()) {
847 cache_req
->memReq
->setExtraData(*write_res
);
851 bool do_access
= true; // flag to suppress cache access
853 Request
*memReq
= cache_req
->dataPkt
->req
;
855 if (cache_req
->dataPkt
->isWrite() && cache_req
->memReq
->isLLSC()) {
856 assert(cache_req
->inst
->isStoreConditional());
857 DPRINTF(InOrderCachePort
, "Evaluating Store Conditional access\n");
858 do_access
= TheISA::handleLockedWrite(cpu
, memReq
);
861 DPRINTF(InOrderCachePort
,
862 "[tid:%i] [sn:%i] attempting to access cache\n",
866 if (!cachePort
->sendTiming(cache_req
->dataPkt
)) {
867 DPRINTF(InOrderCachePort
,
868 "[tid:%i] [sn:%i] cannot access cache, because port "
869 "is blocked. now waiting to retry request\n", tid
,
871 cache_req
->setCompleted(false);
872 cachePortBlocked
= true;
874 DPRINTF(InOrderCachePort
,
875 "[tid:%i] [sn:%i] is now waiting for cache response\n",
877 cache_req
->setCompleted();
878 cache_req
->setMemAccPending();
879 cachePortBlocked
= false;
881 } else if (!do_access
&& memReq
->isLLSC()){
882 // Store-Conditional instructions complete even if they "failed"
883 assert(cache_req
->inst
->isStoreConditional());
884 cache_req
->setCompleted(true);
887 "[tid:%i]: T%i Ignoring Failed Store Conditional Access\n",
890 processCacheCompletion(cache_req
->dataPkt
);
892 // Make cache request again since access due to
893 // inability to access
894 DPRINTF(InOrderStall
, "STALL: \n");
895 cache_req
->setCompleted(false);
902 CacheUnit::processCacheCompletion(PacketPtr pkt
)
904 // Cast to correct packet type
905 CacheReqPacket
* cache_pkt
= dynamic_cast<CacheReqPacket
*>(pkt
);
909 if (cache_pkt
->cacheReq
->isSquashed()) {
910 DPRINTF(InOrderCachePort
,
911 "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n",
912 cache_pkt
->cacheReq
->getInst()->readTid(),
913 cache_pkt
->cacheReq
->getInst()->seqNum
);
915 cache_pkt
->cacheReq
->done();
923 DPRINTF(InOrderCachePort
,
924 "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p\n",
925 cache_pkt
->cacheReq
->getInst()->readTid(),
926 cache_pkt
->cacheReq
->getInst()->seqNum
,
927 cache_pkt
->cacheReq
->getInst()->getMemAddr());
929 // Cast to correct request type
930 CacheRequest
*cache_req
= dynamic_cast<CacheReqPtr
>(
931 findSplitRequest(cache_pkt
->cacheReq
->getInst(), cache_pkt
->instIdx
));
935 "[tid:%u]: [sn:%i]: Can't find slot for cache access to addr. %08p\n",
936 cache_pkt
->cacheReq
->getInst()->readTid(),
937 cache_pkt
->cacheReq
->getInst()->seqNum
,
938 cache_pkt
->cacheReq
->getInst()->getMemAddr());
944 // Get resource request info
945 unsigned stage_num
= cache_req
->getStageNum();
946 DynInstPtr inst
= cache_req
->inst
;
947 ThreadID tid
= cache_req
->inst
->readTid();
949 if (!cache_req
->isSquashed()) {
950 if (inst
->resSched
.top()->cmd
== CompleteFetch
) {
951 DPRINTF(InOrderCachePort
,
952 "[tid:%u]: [sn:%i]: Processing fetch access\n",
955 // NOTE: This is only allowing a thread to fetch one line
956 // at a time. Re-examine when/if prefetching
958 //memcpy(fetchData[tid], cache_pkt->getPtr<uint8_t>(),
959 // cache_pkt->getSize());
961 // Get the instruction from the array of the cache line.
962 // @todo: update thsi
963 ExtMachInst ext_inst
;
964 StaticInstPtr staticInst
= NULL
;
965 Addr inst_pc
= inst
->readPC();
967 TheISA::gtoh(*reinterpret_cast<TheISA::MachInst
*>
968 (cache_pkt
->getPtr
<uint8_t>()));
970 predecoder
.setTC(cpu
->thread
[tid
]->getTC());
971 predecoder
.moreBytes(inst_pc
, inst_pc
, mach_inst
);
972 ext_inst
= predecoder
.getExtMachInst();
974 inst
->setMachInst(ext_inst
);
976 // Set Up More TraceData info
977 if (inst
->traceData
) {
978 inst
->traceData
->setStaticInst(inst
->staticInst
);
979 inst
->traceData
->setPC(inst
->readPC());
982 } else if (inst
->staticInst
&& inst
->isMemRef()) {
983 DPRINTF(InOrderCachePort
,
984 "[tid:%u]: [sn:%i]: Processing cache access\n",
987 if (inst
->splitInst
) {
988 inst
->splitFinishCnt
++;
990 if (inst
->splitFinishCnt
== 2) {
991 cache_req
->memReq
->setVirt(0/*inst->tid*/,
993 inst
->splitTotalSize
,
997 Packet
split_pkt(cache_req
->memReq
, cache_req
->pktCmd
,
1001 if (inst
->isLoad()) {
1002 split_pkt
.dataStatic(inst
->splitMemData
);
1004 split_pkt
.dataStatic(&inst
->storeData
);
1007 inst
->completeAcc(&split_pkt
);
1010 inst
->completeAcc(pkt
);
1013 if (inst
->isLoad()) {
1014 assert(cache_pkt
->isRead());
1016 if (cache_pkt
->req
->isLLSC()) {
1017 DPRINTF(InOrderCachePort
,
1018 "[tid:%u]: Handling Load-Linked for [sn:%u]\n",
1020 TheISA::handleLockedRead(cpu
, cache_pkt
->req
);
1023 // @NOTE: Hardcoded to for load instructions. Assumes that
1024 // the dest. idx 0 is always where the data is loaded to.
1025 DPRINTF(InOrderCachePort
,
1026 "[tid:%u]: [sn:%i]: Data loaded was: %08p\n",
1027 tid
, inst
->seqNum
, inst
->readIntResult(0));
1028 DPRINTF(InOrderCachePort
,
1029 "[tid:%u]: [sn:%i]: FP Data loaded was: %08p\n",
1030 tid
, inst
->seqNum
, inst
->readFloatResult(0));
1031 } else if(inst
->isStore()) {
1032 assert(cache_pkt
->isWrite());
1034 DPRINTF(InOrderCachePort
,
1035 "[tid:%u]: [sn:%i]: Data stored was: FIX ME\n",
1036 tid
, inst
->seqNum
/*,
1037 getMemData(cache_pkt)*/);
1043 cache_req
->setMemAccPending(false);
1044 cache_req
->setMemAccCompleted();
1046 if (cache_req
->isMemStall() &&
1047 cpu
->threadModel
== InOrderCPU::SwitchOnCacheMiss
) {
1048 DPRINTF(InOrderCachePort
, "[tid:%u] Waking up from Cache Miss.\n", tid
);
1050 cpu
->activateContext(tid
);
1052 DPRINTF(ThreadModel
, "Activating [tid:%i] after return from cache"
1056 // Wake up the CPU (if it went to sleep and was waiting on this
1057 // completion event).
1060 DPRINTF(Activity
, "[tid:%u] Activating %s due to cache completion\n",
1061 tid
, cpu
->pipelineStage
[stage_num
]->name());
1063 cpu
->switchToActive(stage_num
);
1065 DPRINTF(InOrderCachePort
,
1066 "[tid:%u] Miss on block @ %08p completed, but squashed\n",
1067 tid
, cache_req
->inst
->readPC());
1068 cache_req
->setMemAccCompleted();
1071 inst
->unsetMemAddr();
1075 CacheUnit::recvRetry()
1077 DPRINTF(InOrderCachePort
, "Unblocking Cache Port. \n");
1079 assert(cachePortBlocked
);
1081 // Clear the cache port for use again
1082 cachePortBlocked
= false;
1087 CacheUnitEvent::CacheUnitEvent()
1092 CacheUnitEvent::process()
1094 DynInstPtr inst
= resource
->reqMap
[slotIdx
]->inst
;
1095 int stage_num
= resource
->reqMap
[slotIdx
]->getStageNum();
1096 ThreadID tid
= inst
->threadNumber
;
1097 CacheReqPtr req_ptr
= dynamic_cast<CacheReqPtr
>(resource
->reqMap
[slotIdx
]);
1099 DPRINTF(InOrderTLB
, "Waking up from TLB Miss caused by [sn:%i].\n",
1102 CacheUnit
* tlb_res
= dynamic_cast<CacheUnit
*>(resource
);
1105 tlb_res
->tlbBlocked
[tid
] = false;
1107 tlb_res
->cpu
->pipelineStage
[stage_num
]->
1108 unsetResStall(tlb_res
->reqMap
[slotIdx
], tid
);
1110 req_ptr
->tlbStall
= false;
1112 if (req_ptr
->isSquashed()) {
1118 CacheUnit::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
1119 InstSeqNum squash_seq_num
, ThreadID tid
)
1121 // If squashing due to memory stall, then we do NOT want to
1122 // squash the instruction that caused the stall so we
1123 // increment the sequence number here to prevent that.
1125 // NOTE: This is only for the SwitchOnCacheMiss Model
1126 // NOTE: If you have multiple outstanding misses from the same
1127 // thread then you need to reevaluate this code
1128 // NOTE: squash should originate from
1129 // pipeline_stage.cc:processInstSchedule
1130 DPRINTF(InOrderCachePort
, "Squashing above [sn:%u]\n",
1131 squash_seq_num
+ 1);
1133 squash(inst
, stage_num
, squash_seq_num
+ 1, tid
);
1138 CacheUnit::squash(DynInstPtr inst
, int stage_num
,
1139 InstSeqNum squash_seq_num
, ThreadID tid
)
1141 vector
<int> slot_remove_list
;
1143 map
<int, ResReqPtr
>::iterator map_it
= reqMap
.begin();
1144 map
<int, ResReqPtr
>::iterator map_end
= reqMap
.end();
1146 while (map_it
!= map_end
) {
1147 ResReqPtr req_ptr
= (*map_it
).second
;
1150 req_ptr
->getInst()->readTid() == tid
&&
1151 req_ptr
->getInst()->seqNum
> squash_seq_num
) {
1153 DPRINTF(InOrderCachePort
,
1154 "[tid:%i] Squashing request from [sn:%i]\n",
1155 req_ptr
->getInst()->readTid(), req_ptr
->getInst()->seqNum
);
1157 req_ptr
->setSquashed();
1159 req_ptr
->getInst()->setSquashed();
1161 CacheReqPtr cache_req
= dynamic_cast<CacheReqPtr
>(req_ptr
);
1164 int req_slot_num
= req_ptr
->getSlot();
1166 if (cache_req
->tlbStall
) {
1167 tlbBlocked
[tid
] = false;
1169 int stall_stage
= reqMap
[req_slot_num
]->getStageNum();
1171 cpu
->pipelineStage
[stall_stage
]->
1172 unsetResStall(reqMap
[req_slot_num
], tid
);
1175 if (!cache_req
->tlbStall
&& !cache_req
->isMemAccPending()) {
1176 // Mark request for later removal
1177 cpu
->reqRemoveList
.push(req_ptr
);
1179 // Mark slot for removal from resource
1180 slot_remove_list
.push_back(req_ptr
->getSlot());
1187 // Now Delete Slot Entry from Req. Map
1188 for (int i
= 0; i
< slot_remove_list
.size(); i
++)
1189 freeSlot(slot_remove_list
[i
]);
1193 CacheUnit::getMemData(Packet
*packet
)
1195 switch (packet
->getSize())
1198 return packet
->get
<uint8_t>();
1201 return packet
->get
<uint16_t>();
1204 return packet
->get
<uint32_t>();
1207 return packet
->get
<uint64_t>();
1210 panic("bad store data size = %d\n", packet
->getSize());
1214 // Extra Template Definitions
1215 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1219 CacheUnit::read(DynInstPtr inst
, Addr addr
, Twin32_t
&data
, unsigned flags
);
1223 CacheUnit::read(DynInstPtr inst
, Addr addr
, Twin64_t
&data
, unsigned flags
);
1227 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint64_t &data
, unsigned flags
);
1231 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint32_t &data
, unsigned flags
);
1235 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint16_t &data
, unsigned flags
);
1239 CacheUnit::read(DynInstPtr inst
, Addr addr
, uint8_t &data
, unsigned flags
);
1241 #endif //DOXYGEN_SHOULD_SKIP_THIS
1245 CacheUnit::read(DynInstPtr inst
, Addr addr
, double &data
, unsigned flags
)
1247 return read(inst
, addr
, *(uint64_t*)&data
, flags
);
1252 CacheUnit::read(DynInstPtr inst
, Addr addr
, float &data
, unsigned flags
)
1254 return read(inst
, addr
, *(uint32_t*)&data
, flags
);
1260 CacheUnit::read(DynInstPtr inst
, Addr addr
, int32_t &data
, unsigned flags
)
1262 return read(inst
, addr
, (uint32_t&)data
, flags
);
1265 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1269 CacheUnit::write(DynInstPtr inst
, Twin32_t data
, Addr addr
,
1270 unsigned flags
, uint64_t *res
);
1274 CacheUnit::write(DynInstPtr inst
, Twin64_t data
, Addr addr
,
1275 unsigned flags
, uint64_t *res
);
1279 CacheUnit::write(DynInstPtr inst
, uint64_t data
, Addr addr
,
1280 unsigned flags
, uint64_t *res
);
1284 CacheUnit::write(DynInstPtr inst
, uint32_t data
, Addr addr
,
1285 unsigned flags
, uint64_t *res
);
1289 CacheUnit::write(DynInstPtr inst
, uint16_t data
, Addr addr
,
1290 unsigned flags
, uint64_t *res
);
1294 CacheUnit::write(DynInstPtr inst
, uint8_t data
, Addr addr
,
1295 unsigned flags
, uint64_t *res
);
1297 #endif //DOXYGEN_SHOULD_SKIP_THIS
1301 CacheUnit::write(DynInstPtr inst
, double data
, Addr addr
, unsigned flags
,
1304 return write(inst
, *(uint64_t*)&data
, addr
, flags
, res
);
1309 CacheUnit::write(DynInstPtr inst
, float data
, Addr addr
, unsigned flags
,
1312 return write(inst
, *(uint32_t*)&data
, addr
, flags
, res
);
1318 CacheUnit::write(DynInstPtr inst
, int32_t data
, Addr addr
, unsigned flags
,
1321 return write(inst
, (uint32_t)data
, addr
, flags
, res
);