bb9ec044519f579933ff7c5fbe9579b532186b38
2 * Copyright (c) 2006 The Regents of The University of Michigan
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.
32 #include "base/refcnt.hh"
33 #include "cpu/base.hh"
34 #include "cpu/base_dyn_inst.hh"
35 #include "cpu/checker/cpu.hh"
36 #include "cpu/cpu_exec_context.hh"
37 #include "cpu/exec_context.hh"
38 #include "cpu/static_inst.hh"
39 #include "sim/byteswap.hh"
40 #include "sim/sim_object.hh"
41 #include "sim/stats.hh"
43 #include "cpu/o3/alpha_dyn_inst.hh"
44 #include "cpu/o3/alpha_impl.hh"
46 //#include "cpu/ozone/dyn_inst.hh"
47 //#include "cpu/ozone/ozone_impl.hh"
48 //#include "cpu/ozone/simple_impl.hh"
51 #include "sim/system.hh"
52 #include "arch/vtophys.hh"
56 //The CheckerCPU does alpha only
57 using namespace AlphaISA
;
64 CheckerCPU::CheckerCPU(Params
*p
)
65 : BaseCPU(p
), cpuXC(NULL
), xcProxy(NULL
)
67 memReq
= new Request();
68 // memReq->data = new uint8_t[64];
76 changedPC
= willChangePC
= changedNextPC
= false;
78 exitOnError
= p
->exitOnError
;
87 CheckerCPU::~CheckerCPU()
92 CheckerCPU::setMemory(MemObject
*mem
)
96 cpuXC
= new CPUExecContext(this, /* thread_num */ 0, NULL
,
99 cpuXC
->setStatus(ExecContext::Suspended
);
100 xcProxy
= cpuXC
->getProxy();
101 execContexts
.push_back(xcProxy
);
104 cpuXC
= new CPUExecContext(this, 0, systemPtr
, itb
, dtb
, memPtr
, false);
106 cpuXC
->setStatus(ExecContext::Suspended
);
107 xcProxy
= cpuXC
->getProxy();
108 execContexts
.push_back(xcProxy
);
109 memReq
->xc
= xcProxy
;
110 delete cpuXC
->kernelStats
;
111 cpuXC
->kernelStats
= NULL
;
118 CheckerCPU::setSystem(System
*system
)
123 cpuXC
= new CPUExecContext(this, 0, systemPtr
, itb
, dtb
, memPtr
, false);
125 cpuXC
->setStatus(ExecContext::Suspended
);
126 xcProxy
= cpuXC
->getProxy();
127 execContexts
.push_back(xcProxy
);
128 memReq
->xc
= xcProxy
;
129 delete cpuXC
->kernelStats
;
130 cpuXC
->kernelStats
= NULL
;
136 CheckerCPU::serialize(ostream
&os
)
139 BaseCPU::serialize(os);
140 SERIALIZE_SCALAR(inst);
141 nameOut(os, csprintf("%s.xc", name()));
142 cpuXC->serialize(os);
143 cacheCompletionEvent.serialize(os);
148 CheckerCPU::unserialize(Checkpoint
*cp
, const string
§ion
)
151 BaseCPU::unserialize(cp, section);
152 UNSERIALIZE_SCALAR(inst);
153 cpuXC->unserialize(cp, csprintf("%s.xc", section));
158 CheckerCPU::copySrcTranslate(Addr src
)
160 panic("Unimplemented!");
164 CheckerCPU::copy(Addr dest
)
166 panic("Unimplemented!");
171 CheckerCPU::read(Addr addr
, T
&data
, unsigned flags
)
174 memReq->reset(addr, sizeof(T), flags);
176 // translate to physical address
177 translateDataReadReq(memReq);
180 memReq->completionEvent = NULL;
181 memReq->time = curTick;
182 memReq->flags &= ~INST_READ;
184 if (!(memReq->flags & UNCACHEABLE)) {
185 // Access memory to see if we have the same data
186 cpuXC->read(memReq, data);
188 // Assume the data is correct if it's an uncached access
189 memcpy(&data, &unverifiedResult.integer, sizeof(T));
195 #ifndef DOXYGEN_SHOULD_SKIP_THIS
199 CheckerCPU::read(Addr addr
, uint64_t &data
, unsigned flags
);
203 CheckerCPU::read(Addr addr
, uint32_t &data
, unsigned flags
);
207 CheckerCPU::read(Addr addr
, uint16_t &data
, unsigned flags
);
211 CheckerCPU::read(Addr addr
, uint8_t &data
, unsigned flags
);
213 #endif //DOXYGEN_SHOULD_SKIP_THIS
217 CheckerCPU::read(Addr addr
, double &data
, unsigned flags
)
219 return read(addr
, *(uint64_t*)&data
, flags
);
224 CheckerCPU::read(Addr addr
, float &data
, unsigned flags
)
226 return read(addr
, *(uint32_t*)&data
, flags
);
231 CheckerCPU::read(Addr addr
, int32_t &data
, unsigned flags
)
233 return read(addr
, (uint32_t&)data
, flags
);
238 CheckerCPU::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
241 memReq->reset(addr, sizeof(T), flags);
243 // translate to physical address
244 cpuXC->translateDataWriteReq(memReq);
246 // Can compare the write data and result only if it's cacheable,
247 // not a store conditional, or is a store conditional that
249 // @todo: Verify that actual memory matches up with these values.
250 // Right now it only verifies that the instruction data is the
251 // same as what was in the request that got sent to memory; there
252 // is no verification that it is the same as what is in memory.
253 // This is because the LSQ would have to be snooped in the CPU to
256 !(unverifiedReq->flags & UNCACHEABLE) &&
257 (!(unverifiedReq->flags & LOCKED) ||
258 ((unverifiedReq->flags & LOCKED) &&
259 unverifiedReq->result == 1))) {
262 memReq->completionEvent = NULL;
263 memReq->time = curTick;
264 memReq->flags &= ~INST_READ;
265 cpuXC->read(memReq, inst_data);
268 memcpy(&inst_data, unverifiedReq->data, sizeof(T));
270 if (data != inst_data) {
271 warn("%lli: Store value does not match value in memory! "
272 "Instruction: %#x, memory: %#x",
273 curTick, inst_data, data);
278 // Assume the result was the same as the one passed in. This checker
279 // doesn't check if the SC should succeed or fail, it just checks the
282 *res = unverifiedReq->result;
288 #ifndef DOXYGEN_SHOULD_SKIP_THIS
291 CheckerCPU::write(uint64_t data
, Addr addr
, unsigned flags
, uint64_t *res
);
295 CheckerCPU::write(uint32_t data
, Addr addr
, unsigned flags
, uint64_t *res
);
299 CheckerCPU::write(uint16_t data
, Addr addr
, unsigned flags
, uint64_t *res
);
303 CheckerCPU::write(uint8_t data
, Addr addr
, unsigned flags
, uint64_t *res
);
305 #endif //DOXYGEN_SHOULD_SKIP_THIS
309 CheckerCPU::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
311 return write(*(uint64_t*)&data
, addr
, flags
, res
);
316 CheckerCPU::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
318 return write(*(uint32_t*)&data
, addr
, flags
, res
);
323 CheckerCPU::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
325 return write((uint32_t)data
, addr
, flags
, res
);
331 CheckerCPU::dbg_vtophys(Addr addr
)
333 return vtophys(xcProxy
, addr
);
335 #endif // FULL_SYSTEM
338 CheckerCPU::translateInstReq(Request
*req
)
341 return (cpuXC
->translateInstReq(req
) == NoFault
);
343 cpuXC
->translateInstReq(req
);
349 CheckerCPU::translateDataReadReq(Request
*req
)
351 cpuXC
->translateDataReadReq(req
);
353 if (req
->getVaddr() != unverifiedReq
->getVaddr()) {
354 warn("%lli: Request virtual addresses do not match! Inst: %#x, "
356 curTick
, unverifiedReq
->getVaddr(), req
->getVaddr());
359 req
->setPaddr(unverifiedReq
->getPaddr());
361 if (checkFlags(req
)) {
362 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
363 curTick
, unverifiedReq
->getFlags(), req
->getFlags());
369 CheckerCPU::translateDataWriteReq(Request
*req
)
371 cpuXC
->translateDataWriteReq(req
);
373 if (req
->getVaddr() != unverifiedReq
->getVaddr()) {
374 warn("%lli: Request virtual addresses do not match! Inst: %#x, "
376 curTick
, unverifiedReq
->getVaddr(), req
->getVaddr());
379 req
->setPaddr(unverifiedReq
->getPaddr());
381 if (checkFlags(req
)) {
382 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
383 curTick
, unverifiedReq
->getFlags(), req
->getFlags());
389 CheckerCPU::checkFlags(Request
*req
)
391 // Remove any dynamic flags that don't have to do with the request itself.
392 unsigned flags
= unverifiedReq
->getFlags();
393 unsigned mask
= LOCKED
| PHYSICAL
| VPTE
| ALTMODE
| UNCACHEABLE
| NO_FAULT
;
394 flags
= flags
& (mask
);
395 if (flags
== req
->getFlags()) {
402 template <class DynInstPtr
>
404 Checker
<DynInstPtr
>::tick(DynInstPtr
&completed_inst
)
408 // Either check this instruction, or add it to a list of
409 // instructions waiting to be checked. Instructions must be
410 // checked in program order, so if a store has committed yet not
411 // completed, there may be some instructions that are waiting
412 // behind it that have completed and must be checked.
413 if (!instList
.empty()) {
414 if (youngestSN
< completed_inst
->seqNum
) {
415 DPRINTF(Checker
, "Adding instruction [sn:%lli] PC:%#x to list.\n",
416 completed_inst
->seqNum
, completed_inst
->readPC());
417 instList
.push_back(completed_inst
);
418 youngestSN
= completed_inst
->seqNum
;
421 if (!instList
.front()->isCompleted()) {
424 inst
= instList
.front();
425 instList
.pop_front();
428 if (!completed_inst
->isCompleted()) {
429 if (youngestSN
< completed_inst
->seqNum
) {
430 DPRINTF(Checker
, "Adding instruction [sn:%lli] PC:%#x to list.\n",
431 completed_inst
->seqNum
, completed_inst
->readPC());
432 instList
.push_back(completed_inst
);
433 youngestSN
= completed_inst
->seqNum
;
437 if (youngestSN
< completed_inst
->seqNum
) {
438 inst
= completed_inst
;
439 youngestSN
= completed_inst
->seqNum
;
446 // Try to check all instructions that are completed, ending if we
447 // run out of instructions to check or if an instruction is not
450 DPRINTF(Checker
, "Processing instruction [sn:%lli] PC:%#x.\n",
451 inst
->seqNum
, inst
->readPC());
452 unverifiedResult
.integer
= inst
->readIntResult();
453 unverifiedReq
= inst
->req
;
456 Fault fault
= NoFault
;
458 // maintain $r0 semantics
459 cpuXC
->setIntReg(ZeroReg
, 0);
461 cpuXC
->setFloatRegDouble(ZeroReg
, 0.0);
462 #endif // TARGET_ALPHA
464 // Check if any recent PC changes match up with anything we
465 // expect to happen. This is mostly to check if traps or
466 // PC-based events have occurred in both the checker and CPU.
468 DPRINTF(Checker
, "Changed PC recently to %#x\n",
471 if (newPC
== cpuXC
->readPC()) {
472 DPRINTF(Checker
, "Changed PC matches expected PC\n");
474 warn("%lli: Changed PC does not match expected PC, "
475 "changed: %#x, expected: %#x",
476 curTick
, cpuXC
->readPC(), newPC
);
479 willChangePC
= false;
484 DPRINTF(Checker
, "Changed NextPC recently to %#x\n",
485 cpuXC
->readNextPC());
486 changedNextPC
= false;
489 // Try to fetch the instruction
492 #define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
494 #define IFETCH_FLAGS(pc) 0
497 // set up memory request for instruction fetch
498 // memReq->cmd = Read;
499 // memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
500 // IFETCH_FLAGS(cpuXC->readPC()));
502 bool succeeded
= translateInstReq(memReq
);
505 if (inst
->getFault() == NoFault
) {
506 // In this case the instruction was not a dummy
507 // instruction carrying an ITB fault. In the single
508 // threaded case the ITB should still be able to
509 // translate this instruction; in the SMT case it's
510 // possible that its ITB entry was kicked out.
511 warn("%lli: Instruction PC %#x was not found in the ITB!",
512 curTick
, cpuXC
->readPC());
515 // go to the next instruction
516 cpuXC
->setPC(cpuXC
->readNextPC());
517 cpuXC
->setNextPC(cpuXC
->readNextPC() + sizeof(MachInst
));
521 // The instruction is carrying an ITB fault. Handle
522 // the fault and see if our results match the CPU on
524 fault
= inst
->getFault();
528 if (fault
== NoFault
) {
529 // cpuXC->read(memReq, machInst);
531 // keep an instruction count
534 // decode the instruction
535 machInst
= gtoh(machInst
);
536 // Checks that the instruction matches what we expected it to be.
537 // Checks both the machine instruction and the PC.
540 curStaticInst
= StaticInst::decode(makeExtMI(machInst
,
544 cpuXC
->setInst(machInst
);
545 #endif // FULL_SYSTEM
547 fault
= inst
->getFault();
550 // Either the instruction was a fault and we should process the fault,
551 // or we should just go ahead execute the instruction. This assumes
552 // that the instruction is properly marked as a fault.
553 if (fault
== NoFault
) {
555 cpuXC
->func_exe_inst
++;
557 fault
= curStaticInst
->execute(this, NULL
);
559 // Checks to make sure instrution results are correct.
560 validateExecution(inst
);
562 if (curStaticInst
->isLoad()) {
567 if (fault
!= NoFault
) {
569 fault
->invoke(xcProxy
);
571 newPC
= cpuXC
->readPC();
572 DPRINTF(Checker
, "Fault, PC is now %#x\n", newPC
);
573 #else // !FULL_SYSTEM
574 fatal("fault (%d) detected @ PC 0x%08p", fault
, cpuXC
->readPC());
575 #endif // FULL_SYSTEM
577 #if THE_ISA != MIPS_ISA
578 // go to the next instruction
579 cpuXC
->setPC(cpuXC
->readNextPC());
580 cpuXC
->setNextPC(cpuXC
->readNextPC() + sizeof(MachInst
));
582 // go to the next instruction
583 cpuXC
->setPC(cpuXC
->readNextPC());
584 cpuXC
->setNextPC(cpuXC
->readNextNPC());
585 cpuXC
->setNextNPC(cpuXC
->readNextNPC() + sizeof(MachInst
));
591 // @todo: Determine if these should happen only if the
592 // instruction hasn't faulted. In the SimpleCPU case this may
593 // not be true, but in the O3 or Ozone case this may be true.
597 oldpc
= cpuXC
->readPC();
598 system
->pcEventQueue
.service(xcProxy
);
600 } while (oldpc
!= cpuXC
->readPC());
603 newPC
= cpuXC
->readPC();
604 DPRINTF(Checker
, "PC Event, PC is now %#x\n", newPC
);
608 // @todo: Optionally can check all registers. (Or just those
609 // that have been modified).
612 // Continue verifying instructions if there's another completed
613 // instruction waiting to be verified.
614 if (instList
.empty()) {
616 } else if (instList
.front()->isCompleted()) {
617 inst
= instList
.front();
618 instList
.pop_front();
625 template <class DynInstPtr
>
627 Checker
<DynInstPtr
>::switchOut(Sampler
*s
)
632 template <class DynInstPtr
>
634 Checker
<DynInstPtr
>::takeOverFrom(BaseCPU
*oldCPU
)
638 template <class DynInstPtr
>
640 Checker
<DynInstPtr
>::validateInst(DynInstPtr
&inst
)
642 if (inst
->readPC() != cpuXC
->readPC()) {
643 warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
644 curTick
, inst
->readPC(), cpuXC
->readPC());
646 warn("%lli: Changed PCs recently, may not be an error",
653 MachInst mi
= static_cast<MachInst
>(inst
->staticInst
->machInst
);
655 if (mi
!= machInst
) {
656 warn("%lli: Binary instructions do not match! Inst: %#x, "
658 curTick
, mi
, machInst
);
663 template <class DynInstPtr
>
665 Checker
<DynInstPtr
>::validateExecution(DynInstPtr
&inst
)
667 if (inst
->numDestRegs()) {
668 // @todo: Support more destination registers.
669 if (inst
->isUnverifiable()) {
670 // Unverifiable instructions assume they were executed
671 // properly by the CPU. Grab the result from the
672 // instruction and write it to the register.
673 RegIndex idx
= inst
->destRegIdx(0);
674 if (idx
< TheISA::FP_Base_DepTag
) {
675 cpuXC
->setIntReg(idx
, inst
->readIntResult());
676 } else if (idx
< TheISA::Fpcr_DepTag
) {
677 cpuXC
->setFloatRegBits(idx
, inst
->readIntResult());
679 cpuXC
->setMiscReg(idx
, inst
->readIntResult());
681 } else if (result
.integer
!= inst
->readIntResult()) {
682 warn("%lli: Instruction results do not match! (Results may not "
683 "actually be integers) Inst: %#x, checker: %#x",
684 curTick
, inst
->readIntResult(), result
.integer
);
689 if (inst
->readNextPC() != cpuXC
->readNextPC()) {
690 warn("%lli: Instruction next PCs do not match! Inst: %#x, "
692 curTick
, inst
->readNextPC(), cpuXC
->readNextPC());
696 // Checking side effect registers can be difficult if they are not
697 // checked simultaneously with the execution of the instruction.
698 // This is because other valid instructions may have modified
699 // these registers in the meantime, and their values are not
700 // stored within the DynInst.
701 while (!miscRegIdxs
.empty()) {
702 int misc_reg_idx
= miscRegIdxs
.front();
705 if (inst
->xcBase()->readMiscReg(misc_reg_idx
) !=
706 cpuXC
->readMiscReg(misc_reg_idx
)) {
707 warn("%lli: Misc reg idx %i (side effect) does not match! "
708 "Inst: %#x, checker: %#x",
709 curTick
, misc_reg_idx
,
710 inst
->xcBase()->readMiscReg(misc_reg_idx
),
711 cpuXC
->readMiscReg(misc_reg_idx
));
717 template <class DynInstPtr
>
719 Checker
<DynInstPtr
>::validateState()
723 template <class DynInstPtr
>
725 Checker
<DynInstPtr
>::dumpInsts()
729 InstListIt inst_list_it
= --(instList
.end());
731 cprintf("Inst list size: %i\n", instList
.size());
733 while (inst_list_it
!= instList
.end())
735 cprintf("Instruction:%i\n",
738 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
740 (*inst_list_it
)->readPC(),
741 (*inst_list_it
)->seqNum
,
742 (*inst_list_it
)->threadNumber
,
743 (*inst_list_it
)->isCompleted());
754 //class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
757 class Checker
<RefCountingPtr
<AlphaDynInst
<AlphaSimpleImpl
> > >;