42#ifndef __CPU_CHECKER_CPU_IMPL_HH__
43#define __CPU_CHECKER_CPU_IMPL_HH__
56#include "debug/Checker.hh"
64template <
class DynInstPtr>
83template <
class DynInstPtr>
87 DPRINTF(
Checker,
"IRQ detected at PC: %s with %d insts in buffer\n",
89 DynInstPtr boundaryInst = NULL;
96 (*itr)->setCompleted();
107 (boundaryInst && boundaryInst->isDelayedCommit() &&
108 !boundaryInst->isLastMicroop())) {
109 panic(
"%lli: Trying to take an interrupt in middle of "
110 "a non-interuptable instruction!",
curTick());
117template <
class DynInstPtr>
126 if ((completed_inst->isSerializing() ||
127 completed_inst->isSerializeBefore()) &&
129 (
instList.front()->seqNum != completed_inst->seqNum) : 0)) {
130 panic(
"%lli: Instruction sn:%lli at PC %s is serializing before but is"
131 " entering instList with other instructions\n",
curTick(),
132 completed_inst->seqNum, completed_inst->pcState());
141 if (youngestSN < completed_inst->seqNum) {
143 completed_inst->seqNum, completed_inst->pcState());
148 if (!
instList.front()->isCompleted()) {
155 if (!completed_inst->isCompleted()) {
156 if (youngestSN < completed_inst->seqNum) {
158 completed_inst->seqNum, completed_inst->pcState());
164 if (youngestSN < completed_inst->seqNum) {
165 inst = completed_inst;
175 if (inst->isSerializeAfter() && !
instList.empty()) {
176 panic(
"%lli: Instruction sn:%lli at PC %s is serializing after but is"
177 " exiting instList with other instructions\n",
curTick(),
178 completed_inst->seqNum, completed_inst->pcState());
213 warn(
"%lli: Changed PC does not match expected PC, "
214 "changed: %s, expected: %s",
224 uint64_t fetchOffset = 0;
225 bool fetchDone =
false;
228 fetch_PC = (fetch_PC & pc_mask) + fetchOffset;
233 auto mem_req = std::make_shared<Request>(
235 fetch_PC,
thread->contextId());
237 mem_req->setVirt(fetch_PC,
decoder->moreBytesSize(),
239 thread->pcState().instAddr());
241 fault =
mmu->translateFunctional(
251 warn(
"%lli: Instruction PC %s was not found in the "
279 std::unique_ptr<PCStateBase> pc_state(
280 thread->pcState().clone());
285 pc_state->microPC(),
nullptr);
293 (pc_state->instAddr() & pc_mask) + fetchOffset;
294 decoder->moreBytes(*pc_state, fetch_pc);
301 instPtr =
decoder->decode(*pc_state);
302 thread->pcState(*pc_state);
305 fetchOffset +=
decoder->moreBytesSize();
330 Fault unverifiedFault;
369 panic(
"%lli: sn: %lli at PC: %s took a fault in checker "
370 "but not in driver CPU\n",
curTick(),
373 panic(
"%lli: sn: %lli at PC: %s took a fault in driver "
374 "CPU but not in checker\n",
curTick(),
399 oldpc =
thread->pcState().instAddr();
400 thread->pcEventQueue.service(oldpc,
tc);
402 }
while (oldpc !=
thread->pcState().instAddr());
418 }
else if (
instList.front()->isCompleted()) {
429template <
class DynInstPtr>
436template <
class DynInstPtr>
439template <
class DynInstPtr>
443 if (inst->pcState().instAddr() !=
thread->pcState().instAddr()) {
444 warn(
"%lli: PCs do not match! Inst: %s, checker: %s",
447 warn(
"%lli: Changed PCs recently, may not be an error",
460template <
class DynInstPtr>
467 bool result_mismatch =
false;
469 if (inst->isUnverifiable()) {
474 }
else if (inst->numDestRegs() > 0 && !result.empty()) {
475 DPRINTF(
Checker,
"Dest regs %d, number of checker dest regs %d\n",
476 inst->numDestRegs(), result.size());
477 for (
int i = 0;
i < inst->numDestRegs() && !result.empty();
i++) {
478 checker_val = result.front();
480 inst_val = inst->popResult();
481 if (checker_val != inst_val) {
482 result_mismatch =
true;
492 if (result_mismatch) {
493 warn(
"%lli: Instruction results (%i) do not match! Inst: %s, "
511 if (inst->pcState() != thread->pcState()) {
512 warn(
"%lli: Instruction PCs do not match! Inst: %s, checker: %s",
513 curTick(), inst->pcState(), thread->pcState());
522 while (!miscRegIdxs.empty()) {
523 int misc_reg_idx = miscRegIdxs.front();
526 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) !=
527 thread->readMiscRegNoEffect(misc_reg_idx)) {
528 warn(
"%lli: Misc reg idx %i (side effect) does not match! "
529 "Inst: %#x, checker: %#x",
531 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx),
532 thread->readMiscRegNoEffect(misc_reg_idx));
542template <
class DynInstPtr>
548 panic(
"%lli: Instruction PC %#x results didn't match up, copying all "
549 "registers from main CPU",
curTick(),
568template <
class DynInstPtr>
571 const DynInstPtr &inst,
const InstResult& mismatch_val,
int start_idx)
575 if (start_idx >= 0) {
576 const RegId& idx = inst->destRegIdx(start_idx);
582 else if (mismatch_val.
isBlob())
589 for (
int i = start_idx;
i < inst->numDestRegs();
i++) {
590 const RegId& idx = inst->destRegIdx(
i);
591 res = inst->popResult();
604template <
class DynInstPtr>
608 cprintf(
"Error detected, instruction information:\n");
609 cprintf(
"PC:%s\n[sn:%lli]\n[tid:%i]\n"
614 inst->isCompleted());
619template <
class DynInstPtr>
629 while (inst_list_it !=
instList.end())
634 cprintf(
"PC:%s\n[sn:%lli]\n[tid:%i]\n"
636 (*inst_list_it)->pcState(),
637 (*inst_list_it)->seqNum,
638 (*inst_list_it)->threadNumber,
639 (*inst_list_it)->isCompleted());
trace::InstTracer * tracer
gem5::BaseCPU::BaseCPUStats baseStats
StaticInstPtr curStaticInst
std::unique_ptr< PCStateBase > newPCState
std::queue< InstResult > result
const PCStateBase & pcState() const override
RequestorID requestorId
id attached to all issued requests
uint8_t * unverifiedMemData
StaticInstPtr curMacroStaticInst
void validateExecution(const DynInstPtr &inst)
DynInstPtr unverifiedInst
void verify(const DynInstPtr &inst)
void validateInst(const DynInstPtr &inst)
std::list< DynInstPtr > instList
void advancePC(const Fault &fault)
void copyResult(const gem5::RefCountingPtr< DynInst > &inst, const InstResult &mismatch_val, int start_idx)
void handleError(const DynInstPtr &inst)
void switchOut()
Prepare for another CPU to take over execution.
std::list< DynInstPtr >::iterator InstListIt
void takeOverFrom(BaseCPU *oldCPU)
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
std::string asString() const
const void * asBlob() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Register ID: describe an architectural register with its class and index.
constexpr RegClassType classValue() const
constexpr RegIndex index() const
Index accessors.
@ INST_FETCH
The request was an instruction fetch.
virtual StaticInstPtr fetchMicroop(MicroPC upc) const
Return the microop that goes with a particular micropc.
#define panic(...)
This implements a cprintf based panic() function.
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
void cprintf(const char *format, const Args &...args)
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
RefCountingPtr< StaticInst > StaticInstPtr
static bool isRomMicroPC(MicroPC upc)
const StaticInstPtr nullStaticInstPtr
Statically allocated null StaticInstPtr.
constexpr decltype(nullptr) NoFault
@ MiscRegClass
Control (misc) register.
Classes for managing reference counted objects.