1/* 2 * Copyright (c) 2011, 2016-2018 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Kevin Lim 42 */ 43 44#ifndef __CPU_CHECKER_CPU_HH__ 45#define __CPU_CHECKER_CPU_HH__ 46 47#include <list> 48#include <map> 49#include <queue> 50 51#include "arch/types.hh" 52#include "base/statistics.hh" 53#include "cpu/base.hh" 54#include "cpu/base_dyn_inst.hh" 55#include "cpu/exec_context.hh" 56#include "cpu/inst_res.hh" 57#include "cpu/pc_event.hh" 58#include "cpu/simple_thread.hh" 59#include "cpu/static_inst.hh" 60#include "debug/Checker.hh" 61#include "mem/request.hh" 62#include "params/CheckerCPU.hh" 63#include "sim/eventq.hh" 64 65class BaseTLB; 66template <class> 67class BaseDynInst; 68class ThreadContext; 69class Request; 70 71/** 72 * CheckerCPU class. Dynamically verifies instructions as they are 73 * completed by making sure that the instruction and its results match 74 * the independent execution of the benchmark inside the checker. The 75 * checker verifies instructions in order, regardless of the order in 76 * which instructions complete. There are certain results that can 77 * not be verified, specifically the result of a store conditional or 78 * the values of uncached accesses. In these cases, and with 79 * instructions marked as "IsUnverifiable", the checker assumes that 80 * the value from the main CPU's execution is correct and simply 81 * copies that value. It provides a CheckerThreadContext (see 82 * checker/thread_context.hh) that provides hooks for updating the 83 * Checker's state through any ThreadContext accesses. This allows the 84 * checker to be able to correctly verify instructions, even with 85 * external accesses to the ThreadContext that change state. 86 */ 87class CheckerCPU : public BaseCPU, public ExecContext 88{ 89 protected: 90 typedef TheISA::MachInst MachInst; 91 using VecRegContainer = TheISA::VecRegContainer; 92 93 /** id attached to all issued requests */ 94 MasterID masterId; 95 public: 96 void init() override; 97 98 typedef CheckerCPUParams Params; 99 CheckerCPU(Params *p); 100 virtual ~CheckerCPU(); 101 102 void setSystem(System *system); 103 104 void setIcachePort(MasterPort *icache_port); 105 106 void setDcachePort(MasterPort *dcache_port); 107 108 Port & 109 getDataPort() override 110 { 111 // the checker does not have ports on its own so return the 112 // data port of the actual CPU core 113 assert(dcachePort); 114 return *dcachePort; 115 } 116 117 Port & 118 getInstPort() override 119 { 120 // the checker does not have ports on its own so return the 121 // data port of the actual CPU core 122 assert(icachePort); 123 return *icachePort; 124 } 125 126 protected: 127 128 std::vector<Process*> workload; 129 130 System *systemPtr; 131 132 MasterPort *icachePort; 133 MasterPort *dcachePort; 134 135 ThreadContext *tc; 136 137 BaseTLB *itb; 138 BaseTLB *dtb; 139 140 Addr dbg_vtophys(Addr addr); 141 142 // ISAs like ARM can have multiple destination registers to check, 143 // keep them all in a std::queue 144 std::queue<InstResult> result; 145 146 StaticInstPtr curStaticInst; 147 StaticInstPtr curMacroStaticInst; 148 149 // number of simulated instructions 150 Counter numInst; 151 Counter startNumInst; 152 153 std::queue<int> miscRegIdxs; 154 155 public: 156 157 // Primary thread being run. 158 SimpleThread *thread; 159 160 BaseTLB* getITBPtr() { return itb; } 161 BaseTLB* getDTBPtr() { return dtb; } 162 163 virtual Counter totalInsts() const override 164 { 165 return 0; 166 } 167 168 virtual Counter totalOps() const override 169 { 170 return 0; 171 } 172 173 // number of simulated loads 174 Counter numLoad; 175 Counter startNumLoad; 176 177 void serialize(CheckpointOut &cp) const override; 178 void unserialize(CheckpointIn &cp) override; 179 180 // The register accessor methods provide the index of the 181 // instruction's operand (e.g., 0 or 1), not the architectural 182 // register index, to simplify the implementation of register 183 // renaming. We find the architectural register index by indexing 184 // into the instruction's own operand index table. Note that a 185 // raw pointer to the StaticInst is provided instead of a 186 // ref-counted StaticInstPtr to redice overhead. This is fine as 187 // long as these methods don't copy the pointer into any long-term 188 // storage (which is pretty hard to imagine they would have reason 189 // to do). 190 191 RegVal 192 readIntRegOperand(const StaticInst *si, int idx) override 193 { 194 const RegId& reg = si->srcRegIdx(idx); 195 assert(reg.isIntReg()); 196 return thread->readIntReg(reg.index()); 197 } 198 199 RegVal 200 readFloatRegOperandBits(const StaticInst *si, int idx) override 201 { 202 const RegId& reg = si->srcRegIdx(idx); 203 assert(reg.isFloatReg()); 204 return thread->readFloatReg(reg.index()); 205 } 206 207 /** 208 * Read source vector register operand. 209 */ 210 const VecRegContainer & 211 readVecRegOperand(const StaticInst *si, int idx) const override 212 { 213 const RegId& reg = si->srcRegIdx(idx); 214 assert(reg.isVecReg()); 215 return thread->readVecReg(reg); 216 } 217 218 /** 219 * Read destination vector register operand for modification. 220 */ 221 VecRegContainer & 222 getWritableVecRegOperand(const StaticInst *si, int idx) override 223 { 224 const RegId& reg = si->destRegIdx(idx); 225 assert(reg.isVecReg()); 226 return thread->getWritableVecReg(reg); 227 } 228 229 /** Vector Register Lane Interfaces. */ 230 /** @{ */ 231 /** Reads source vector 8bit operand. */ 232 virtual ConstVecLane8 233 readVec8BitLaneOperand(const StaticInst *si, int idx) const override 234 { 235 const RegId& reg = si->destRegIdx(idx); 236 assert(reg.isVecReg()); 237 return thread->readVec8BitLaneReg(reg); 238 } 239 240 /** Reads source vector 16bit operand. */ 241 virtual ConstVecLane16 242 readVec16BitLaneOperand(const StaticInst *si, int idx) const override 243 { 244 const RegId& reg = si->destRegIdx(idx); 245 assert(reg.isVecReg()); 246 return thread->readVec16BitLaneReg(reg); 247 } 248 249 /** Reads source vector 32bit operand. */ 250 virtual ConstVecLane32 251 readVec32BitLaneOperand(const StaticInst *si, int idx) const override 252 { 253 const RegId& reg = si->destRegIdx(idx); 254 assert(reg.isVecReg()); 255 return thread->readVec32BitLaneReg(reg); 256 } 257 258 /** Reads source vector 64bit operand. */ 259 virtual ConstVecLane64 260 readVec64BitLaneOperand(const StaticInst *si, int idx) const override 261 { 262 const RegId& reg = si->destRegIdx(idx); 263 assert(reg.isVecReg()); 264 return thread->readVec64BitLaneReg(reg); 265 } 266 267 /** Write a lane of the destination vector operand. */ 268 template <typename LD> 269 void 270 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val) 271 { 272 const RegId& reg = si->destRegIdx(idx); 273 assert(reg.isVecReg()); 274 return thread->setVecLane(reg, val); 275 } 276 virtual void 277 setVecLaneOperand(const StaticInst *si, int idx, 278 const LaneData<LaneSize::Byte>& val) override 279 { 280 setVecLaneOperandT(si, idx, val); 281 } 282 virtual void 283 setVecLaneOperand(const StaticInst *si, int idx, 284 const LaneData<LaneSize::TwoByte>& val) override 285 { 286 setVecLaneOperandT(si, idx, val); 287 } 288 virtual void 289 setVecLaneOperand(const StaticInst *si, int idx, 290 const LaneData<LaneSize::FourByte>& val) override 291 { 292 setVecLaneOperandT(si, idx, val); 293 } 294 virtual void 295 setVecLaneOperand(const StaticInst *si, int idx, 296 const LaneData<LaneSize::EightByte>& val) override 297 { 298 setVecLaneOperandT(si, idx, val); 299 } 300 /** @} */ 301 302 VecElem 303 readVecElemOperand(const StaticInst *si, int idx) const override 304 { 305 const RegId& reg = si->srcRegIdx(idx); 306 return thread->readVecElem(reg); 307 } 308 309 const VecPredRegContainer& 310 readVecPredRegOperand(const StaticInst *si, int idx) const override 311 { 312 const RegId& reg = si->srcRegIdx(idx); 313 assert(reg.isVecPredReg()); 314 return thread->readVecPredReg(reg); 315 } 316 317 VecPredRegContainer& 318 getWritableVecPredRegOperand(const StaticInst *si, int idx) override 319 { 320 const RegId& reg = si->destRegIdx(idx); 321 assert(reg.isVecPredReg()); 322 return thread->getWritableVecPredReg(reg); 323 } 324 325 RegVal 326 readCCRegOperand(const StaticInst *si, int idx) override 327 { 328 const RegId& reg = si->srcRegIdx(idx); 329 assert(reg.isCCReg()); 330 return thread->readCCReg(reg.index()); 331 } 332 333 template<typename T> 334 void 335 setScalarResult(T&& t) 336 { 337 result.push(InstResult(std::forward<T>(t), 338 InstResult::ResultType::Scalar)); 339 } 340 341 template<typename T> 342 void 343 setVecResult(T&& t) 344 { 345 result.push(InstResult(std::forward<T>(t), 346 InstResult::ResultType::VecReg)); 347 } 348 349 template<typename T> 350 void 351 setVecElemResult(T&& t) 352 { 353 result.push(InstResult(std::forward<T>(t), 354 InstResult::ResultType::VecElem)); 355 } 356 357 template<typename T> 358 void 359 setVecPredResult(T&& t) 360 { 361 result.push(InstResult(std::forward<T>(t), 362 InstResult::ResultType::VecPredReg)); 363 } 364 365 void 366 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override 367 { 368 const RegId& reg = si->destRegIdx(idx); 369 assert(reg.isIntReg()); 370 thread->setIntReg(reg.index(), val); 371 setScalarResult(val); 372 } 373 374 void 375 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override 376 { 377 const RegId& reg = si->destRegIdx(idx); 378 assert(reg.isFloatReg()); 379 thread->setFloatReg(reg.index(), val); 380 setScalarResult(val); 381 } 382 383 void 384 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override 385 { 386 const RegId& reg = si->destRegIdx(idx); 387 assert(reg.isCCReg()); 388 thread->setCCReg(reg.index(), val); 389 setScalarResult((uint64_t)val); 390 } 391 392 void 393 setVecRegOperand(const StaticInst *si, int idx, 394 const VecRegContainer& val) override 395 { 396 const RegId& reg = si->destRegIdx(idx); 397 assert(reg.isVecReg()); 398 thread->setVecReg(reg, val); 399 setVecResult(val); 400 } 401 402 void 403 setVecElemOperand(const StaticInst *si, int idx, 404 const VecElem val) override 405 { 406 const RegId& reg = si->destRegIdx(idx); 407 assert(reg.isVecElem()); 408 thread->setVecElem(reg, val); 409 setVecElemResult(val); 410 } 411 412 void setVecPredRegOperand(const StaticInst *si, int idx, 413 const VecPredRegContainer& val) override 414 { 415 const RegId& reg = si->destRegIdx(idx); 416 assert(reg.isVecPredReg()); 417 thread->setVecPredReg(reg, val); 418 setVecPredResult(val); 419 } 420 421 bool readPredicate() const override { return thread->readPredicate(); } 422 423 void 424 setPredicate(bool val) override 425 { 426 thread->setPredicate(val); 427 } 428 429 bool 430 readMemAccPredicate() const override 431 { 432 return thread->readMemAccPredicate(); 433 } 434 435 void 436 setMemAccPredicate(bool val) override 437 { 438 thread->setMemAccPredicate(val); 439 } 440 441 TheISA::PCState pcState() const override { return thread->pcState(); } 442 void 443 pcState(const TheISA::PCState &val) override 444 { 445 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n", 446 val, thread->pcState()); 447 thread->pcState(val); 448 } 449 Addr instAddr() { return thread->instAddr(); } 450 Addr nextInstAddr() { return thread->nextInstAddr(); } 451 MicroPC microPC() { return thread->microPC(); } 452 ////////////////////////////////////////// 453 454 RegVal 455 readMiscRegNoEffect(int misc_reg) const 456 { 457 return thread->readMiscRegNoEffect(misc_reg); 458 } 459 460 RegVal 461 readMiscReg(int misc_reg) override 462 { 463 return thread->readMiscReg(misc_reg); 464 } 465 466 void 467 setMiscRegNoEffect(int misc_reg, RegVal val) 468 { 469 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", 470 misc_reg); 471 miscRegIdxs.push(misc_reg); 472 return thread->setMiscRegNoEffect(misc_reg, val); 473 } 474 475 void 476 setMiscReg(int misc_reg, RegVal val) override 477 { 478 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", 479 misc_reg); 480 miscRegIdxs.push(misc_reg); 481 return thread->setMiscReg(misc_reg, val); 482 } 483 484 RegVal 485 readMiscRegOperand(const StaticInst *si, int idx) override 486 { 487 const RegId& reg = si->srcRegIdx(idx); 488 assert(reg.isMiscReg()); 489 return thread->readMiscReg(reg.index()); 490 } 491 492 void 493 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override 494 { 495 const RegId& reg = si->destRegIdx(idx); 496 assert(reg.isMiscReg()); 497 return this->setMiscReg(reg.index(), val); 498 } 499 500 ///////////////////////////////////////// 501 502 void 503 recordPCChange(const TheISA::PCState &val) 504 { 505 changedPC = true; 506 newPCState = val; 507 } 508 509 void 510 demapPage(Addr vaddr, uint64_t asn) override 511 { 512 this->itb->demapPage(vaddr, asn); 513 this->dtb->demapPage(vaddr, asn); 514 } 515 516 // monitor/mwait funtions 517 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); } 518 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); } 519 void mwaitAtomic(ThreadContext *tc) override 520 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); } 521 AddressMonitor *getAddrMonitor() override 522 { return BaseCPU::getCpuAddrMonitor(0); } 523 524 void 525 demapInstPage(Addr vaddr, uint64_t asn) 526 { 527 this->itb->demapPage(vaddr, asn); 528 } 529 530 void 531 demapDataPage(Addr vaddr, uint64_t asn) 532 { 533 this->dtb->demapPage(vaddr, asn); 534 } 535 536 /** 537 * Helper function used to generate the request for a single fragment of a 538 * memory access. 539 * 540 * Takes care of setting up the appropriate byte-enable mask for the 541 * fragment, given the mask for the entire memory access. 542 * 543 * @param frag_addr Start address of the fragment. 544 * @param size Total size of the memory access in bytes. 545 * @param flags Request flags. 546 * @param byte_enable Byte-enable mask for the entire memory access. 547 * @param[out] frag_size Fragment size. 548 * @param[in,out] size_left Size left to be processed in the memory access. 549 * @return Pointer to the allocated Request, nullptr if the byte-enable 550 * mask is all-false for the fragment. 551 */ 552 RequestPtr genMemFragmentRequest(Addr frag_addr, int size, 553 Request::Flags flags, 554 const std::vector<bool>& byte_enable, 555 int& frag_size, int& size_left) const; 556 557 Fault readMem(Addr addr, uint8_t *data, unsigned size, 558 Request::Flags flags, 559 const std::vector<bool>& byteEnable = std::vector<bool>()) 560 override; 561 562 Fault writeMem(uint8_t *data, unsigned size, Addr addr, 563 Request::Flags flags, uint64_t *res, 564 const std::vector<bool>& byteEnable = std::vector<bool>()) 565 override; 566 567 Fault amoMem(Addr addr, uint8_t* data, unsigned size, 568 Request::Flags flags, AtomicOpFunctorPtr amo_op) override 569 { 570 panic("AMO is not supported yet in CPU checker\n"); 571 } 572 573 unsigned int 574 readStCondFailures() const override { 575 return thread->readStCondFailures(); 576 } 577 578 void setStCondFailures(unsigned int sc_failures) override {} 579 ///////////////////////////////////////////////////// 580 581 void wakeup(ThreadID tid) override { } 582 // Assume that the normal CPU's call to syscall was successful. 583 // The checker's state would have already been updated by the syscall. 584 void syscall(int64_t callnum, Fault *fault) override { } 585 586 void 587 handleError() 588 { 589 if (exitOnError) 590 dumpAndExit(); 591 } 592 593 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr, 594 Addr pAddr, int flags); 595 596 void dumpAndExit(); 597 598 ThreadContext *tcBase() override { return tc; } 599 SimpleThread *threadBase() { return thread; } 600 601 InstResult unverifiedResult; 602 RequestPtr unverifiedReq; 603 uint8_t *unverifiedMemData; 604 605 bool changedPC; 606 bool willChangePC; 607 TheISA::PCState newPCState; 608 bool exitOnError; 609 bool updateOnError; 610 bool warnOnlyOnLoadError; 611 612 InstSeqNum youngestSN; 613}; 614 615/** 616 * Templated Checker class. This Checker class is templated on the 617 * DynInstPtr of the instruction type that will be verified. Proper 618 * template instantiations of the Checker must be placed at the bottom 619 * of checker/cpu.cc. 620 */ 621template <class Impl> 622class Checker : public CheckerCPU 623{ 624 private: 625 typedef typename Impl::DynInstPtr DynInstPtr; 626 627 public: 628 Checker(Params *p) 629 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL) 630 { } 631 632 void switchOut(); 633 void takeOverFrom(BaseCPU *oldCPU); 634 635 void advancePC(const Fault &fault); 636 637 void verify(const DynInstPtr &inst); 638 639 void validateInst(const DynInstPtr &inst); 640 void validateExecution(const DynInstPtr &inst); 641 void validateState(); 642 643 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val, 644 int start_idx); 645 void handlePendingInt(); 646 647 private: 648 void handleError(const DynInstPtr &inst) 649 { 650 if (exitOnError) { 651 dumpAndExit(inst); 652 } else if (updateOnError) { 653 updateThisCycle = true; 654 } 655 } 656 657 void dumpAndExit(const DynInstPtr &inst); 658 659 bool updateThisCycle; 660 661 DynInstPtr unverifiedInst; 662 663 std::list<DynInstPtr> instList; 664 typedef typename std::list<DynInstPtr>::iterator InstListIt; 665 void dumpInsts(); 666}; 667 668#endif // __CPU_CHECKER_CPU_HH__ 669