cpu.hh revision 13622
1/* 2 * Copyright (c) 2011, 2016-2017 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 MasterPort &getDataPort() override 109 { 110 // the checker does not have ports on its own so return the 111 // data port of the actual CPU core 112 assert(dcachePort); 113 return *dcachePort; 114 } 115 116 MasterPort &getInstPort() override 117 { 118 // the checker does not have ports on its own so return the 119 // data port of the actual CPU core 120 assert(icachePort); 121 return *icachePort; 122 } 123 124 protected: 125 126 std::vector<Process*> workload; 127 128 System *systemPtr; 129 130 MasterPort *icachePort; 131 MasterPort *dcachePort; 132 133 ThreadContext *tc; 134 135 BaseTLB *itb; 136 BaseTLB *dtb; 137 138 Addr dbg_vtophys(Addr addr); 139 140 // ISAs like ARM can have multiple destination registers to check, 141 // keep them all in a std::queue 142 std::queue<InstResult> result; 143 144 StaticInstPtr curStaticInst; 145 StaticInstPtr curMacroStaticInst; 146 147 // number of simulated instructions 148 Counter numInst; 149 Counter startNumInst; 150 151 std::queue<int> miscRegIdxs; 152 153 public: 154 155 // Primary thread being run. 156 SimpleThread *thread; 157 158 BaseTLB* getITBPtr() { return itb; } 159 BaseTLB* getDTBPtr() { return dtb; } 160 161 virtual Counter totalInsts() const override 162 { 163 return 0; 164 } 165 166 virtual Counter totalOps() const override 167 { 168 return 0; 169 } 170 171 // number of simulated loads 172 Counter numLoad; 173 Counter startNumLoad; 174 175 void serialize(CheckpointOut &cp) const override; 176 void unserialize(CheckpointIn &cp) override; 177 178 // The register accessor methods provide the index of the 179 // instruction's operand (e.g., 0 or 1), not the architectural 180 // register index, to simplify the implementation of register 181 // renaming. We find the architectural register index by indexing 182 // into the instruction's own operand index table. Note that a 183 // raw pointer to the StaticInst is provided instead of a 184 // ref-counted StaticInstPtr to redice overhead. This is fine as 185 // long as these methods don't copy the pointer into any long-term 186 // storage (which is pretty hard to imagine they would have reason 187 // to do). 188 189 RegVal 190 readIntRegOperand(const StaticInst *si, int idx) override 191 { 192 const RegId& reg = si->srcRegIdx(idx); 193 assert(reg.isIntReg()); 194 return thread->readIntReg(reg.index()); 195 } 196 197 RegVal 198 readFloatRegOperandBits(const StaticInst *si, int idx) override 199 { 200 const RegId& reg = si->srcRegIdx(idx); 201 assert(reg.isFloatReg()); 202 return thread->readFloatReg(reg.index()); 203 } 204 205 /** 206 * Read source vector register operand. 207 */ 208 const VecRegContainer & 209 readVecRegOperand(const StaticInst *si, int idx) const override 210 { 211 const RegId& reg = si->srcRegIdx(idx); 212 assert(reg.isVecReg()); 213 return thread->readVecReg(reg); 214 } 215 216 /** 217 * Read destination vector register operand for modification. 218 */ 219 VecRegContainer & 220 getWritableVecRegOperand(const StaticInst *si, int idx) override 221 { 222 const RegId& reg = si->destRegIdx(idx); 223 assert(reg.isVecReg()); 224 return thread->getWritableVecReg(reg); 225 } 226 227 /** Vector Register Lane Interfaces. */ 228 /** @{ */ 229 /** Reads source vector 8bit operand. */ 230 virtual ConstVecLane8 231 readVec8BitLaneOperand(const StaticInst *si, int idx) const override 232 { 233 const RegId& reg = si->destRegIdx(idx); 234 assert(reg.isVecReg()); 235 return thread->readVec8BitLaneReg(reg); 236 } 237 238 /** Reads source vector 16bit operand. */ 239 virtual ConstVecLane16 240 readVec16BitLaneOperand(const StaticInst *si, int idx) const override 241 { 242 const RegId& reg = si->destRegIdx(idx); 243 assert(reg.isVecReg()); 244 return thread->readVec16BitLaneReg(reg); 245 } 246 247 /** Reads source vector 32bit operand. */ 248 virtual ConstVecLane32 249 readVec32BitLaneOperand(const StaticInst *si, int idx) const override 250 { 251 const RegId& reg = si->destRegIdx(idx); 252 assert(reg.isVecReg()); 253 return thread->readVec32BitLaneReg(reg); 254 } 255 256 /** Reads source vector 64bit operand. */ 257 virtual ConstVecLane64 258 readVec64BitLaneOperand(const StaticInst *si, int idx) const override 259 { 260 const RegId& reg = si->destRegIdx(idx); 261 assert(reg.isVecReg()); 262 return thread->readVec64BitLaneReg(reg); 263 } 264 265 /** Write a lane of the destination vector operand. */ 266 template <typename LD> 267 void 268 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val) 269 { 270 const RegId& reg = si->destRegIdx(idx); 271 assert(reg.isVecReg()); 272 return thread->setVecLane(reg, val); 273 } 274 virtual void 275 setVecLaneOperand(const StaticInst *si, int idx, 276 const LaneData<LaneSize::Byte>& val) override 277 { 278 setVecLaneOperandT(si, idx, val); 279 } 280 virtual void 281 setVecLaneOperand(const StaticInst *si, int idx, 282 const LaneData<LaneSize::TwoByte>& val) override 283 { 284 setVecLaneOperandT(si, idx, val); 285 } 286 virtual void 287 setVecLaneOperand(const StaticInst *si, int idx, 288 const LaneData<LaneSize::FourByte>& val) override 289 { 290 setVecLaneOperandT(si, idx, val); 291 } 292 virtual void 293 setVecLaneOperand(const StaticInst *si, int idx, 294 const LaneData<LaneSize::EightByte>& val) override 295 { 296 setVecLaneOperandT(si, idx, val); 297 } 298 /** @} */ 299 300 VecElem 301 readVecElemOperand(const StaticInst *si, int idx) const override 302 { 303 const RegId& reg = si->srcRegIdx(idx); 304 return thread->readVecElem(reg); 305 } 306 307 const VecPredRegContainer& 308 readVecPredRegOperand(const StaticInst *si, int idx) const override 309 { 310 const RegId& reg = si->srcRegIdx(idx); 311 assert(reg.isVecPredReg()); 312 return thread->readVecPredReg(reg); 313 } 314 315 VecPredRegContainer& 316 getWritableVecPredRegOperand(const StaticInst *si, int idx) override 317 { 318 const RegId& reg = si->destRegIdx(idx); 319 assert(reg.isVecPredReg()); 320 return thread->getWritableVecPredReg(reg); 321 } 322 323 RegVal 324 readCCRegOperand(const StaticInst *si, int idx) override 325 { 326 const RegId& reg = si->srcRegIdx(idx); 327 assert(reg.isCCReg()); 328 return thread->readCCReg(reg.index()); 329 } 330 331 template<typename T> 332 void 333 setScalarResult(T&& t) 334 { 335 result.push(InstResult(std::forward<T>(t), 336 InstResult::ResultType::Scalar)); 337 } 338 339 template<typename T> 340 void 341 setVecResult(T&& t) 342 { 343 result.push(InstResult(std::forward<T>(t), 344 InstResult::ResultType::VecReg)); 345 } 346 347 template<typename T> 348 void 349 setVecElemResult(T&& t) 350 { 351 result.push(InstResult(std::forward<T>(t), 352 InstResult::ResultType::VecElem)); 353 } 354 355 template<typename T> 356 void 357 setVecPredResult(T&& t) 358 { 359 result.push(InstResult(std::forward<T>(t), 360 InstResult::ResultType::VecPredReg)); 361 } 362 363 void 364 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override 365 { 366 const RegId& reg = si->destRegIdx(idx); 367 assert(reg.isIntReg()); 368 thread->setIntReg(reg.index(), val); 369 setScalarResult(val); 370 } 371 372 void 373 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override 374 { 375 const RegId& reg = si->destRegIdx(idx); 376 assert(reg.isFloatReg()); 377 thread->setFloatReg(reg.index(), val); 378 setScalarResult(val); 379 } 380 381 void 382 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override 383 { 384 const RegId& reg = si->destRegIdx(idx); 385 assert(reg.isCCReg()); 386 thread->setCCReg(reg.index(), val); 387 setScalarResult((uint64_t)val); 388 } 389 390 void 391 setVecRegOperand(const StaticInst *si, int idx, 392 const VecRegContainer& val) override 393 { 394 const RegId& reg = si->destRegIdx(idx); 395 assert(reg.isVecReg()); 396 thread->setVecReg(reg, val); 397 setVecResult(val); 398 } 399 400 void 401 setVecElemOperand(const StaticInst *si, int idx, 402 const VecElem val) override 403 { 404 const RegId& reg = si->destRegIdx(idx); 405 assert(reg.isVecElem()); 406 thread->setVecElem(reg, val); 407 setVecElemResult(val); 408 } 409 410 void setVecPredRegOperand(const StaticInst *si, int idx, 411 const VecPredRegContainer& val) override 412 { 413 const RegId& reg = si->destRegIdx(idx); 414 assert(reg.isVecPredReg()); 415 thread->setVecPredReg(reg, val); 416 setVecPredResult(val); 417 } 418 419 bool readPredicate() const override { return thread->readPredicate(); } 420 421 void 422 setPredicate(bool val) override 423 { 424 thread->setPredicate(val); 425 } 426 427 TheISA::PCState pcState() const override { return thread->pcState(); } 428 void 429 pcState(const TheISA::PCState &val) override 430 { 431 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n", 432 val, thread->pcState()); 433 thread->pcState(val); 434 } 435 Addr instAddr() { return thread->instAddr(); } 436 Addr nextInstAddr() { return thread->nextInstAddr(); } 437 MicroPC microPC() { return thread->microPC(); } 438 ////////////////////////////////////////// 439 440 RegVal 441 readMiscRegNoEffect(int misc_reg) const 442 { 443 return thread->readMiscRegNoEffect(misc_reg); 444 } 445 446 RegVal 447 readMiscReg(int misc_reg) override 448 { 449 return thread->readMiscReg(misc_reg); 450 } 451 452 void 453 setMiscRegNoEffect(int misc_reg, RegVal val) 454 { 455 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", 456 misc_reg); 457 miscRegIdxs.push(misc_reg); 458 return thread->setMiscRegNoEffect(misc_reg, val); 459 } 460 461 void 462 setMiscReg(int misc_reg, RegVal val) override 463 { 464 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", 465 misc_reg); 466 miscRegIdxs.push(misc_reg); 467 return thread->setMiscReg(misc_reg, val); 468 } 469 470 RegVal 471 readMiscRegOperand(const StaticInst *si, int idx) override 472 { 473 const RegId& reg = si->srcRegIdx(idx); 474 assert(reg.isMiscReg()); 475 return thread->readMiscReg(reg.index()); 476 } 477 478 void 479 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override 480 { 481 const RegId& reg = si->destRegIdx(idx); 482 assert(reg.isMiscReg()); 483 return this->setMiscReg(reg.index(), val); 484 } 485 486#if THE_ISA == MIPS_ISA 487 RegVal 488 readRegOtherThread(const RegId &misc_reg, ThreadID tid) override 489 { 490 panic("MIPS MT not defined for CheckerCPU.\n"); 491 return 0; 492 } 493 494 void 495 setRegOtherThread(const RegId& misc_reg, RegVal val, ThreadID tid) override 496 { 497 panic("MIPS MT not defined for CheckerCPU.\n"); 498 } 499#endif 500 501 ///////////////////////////////////////// 502 503 void 504 recordPCChange(const TheISA::PCState &val) 505 { 506 changedPC = true; 507 newPCState = val; 508 } 509 510 void 511 demapPage(Addr vaddr, uint64_t asn) override 512 { 513 this->itb->demapPage(vaddr, asn); 514 this->dtb->demapPage(vaddr, asn); 515 } 516 517 // monitor/mwait funtions 518 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); } 519 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); } 520 void mwaitAtomic(ThreadContext *tc) override 521 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); } 522 AddressMonitor *getAddrMonitor() override 523 { return BaseCPU::getCpuAddrMonitor(0); } 524 525 void 526 demapInstPage(Addr vaddr, uint64_t asn) 527 { 528 this->itb->demapPage(vaddr, asn); 529 } 530 531 void 532 demapDataPage(Addr vaddr, uint64_t asn) 533 { 534 this->dtb->demapPage(vaddr, asn); 535 } 536 537 Fault readMem(Addr addr, uint8_t *data, unsigned size, 538 Request::Flags flags) override; 539 Fault writeMem(uint8_t *data, unsigned size, Addr addr, 540 Request::Flags flags, uint64_t *res) override; 541 542 unsigned int 543 readStCondFailures() const override { 544 return thread->readStCondFailures(); 545 } 546 547 void setStCondFailures(unsigned int sc_failures) override {} 548 ///////////////////////////////////////////////////// 549 550 Fault hwrei() override { return thread->hwrei(); } 551 bool simPalCheck(int palFunc) override 552 { return thread->simPalCheck(palFunc); } 553 void wakeup(ThreadID tid) override { } 554 // Assume that the normal CPU's call to syscall was successful. 555 // The checker's state would have already been updated by the syscall. 556 void syscall(int64_t callnum, Fault *fault) override { } 557 558 void 559 handleError() 560 { 561 if (exitOnError) 562 dumpAndExit(); 563 } 564 565 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr, 566 Addr pAddr, int flags); 567 568 void dumpAndExit(); 569 570 ThreadContext *tcBase() override { return tc; } 571 SimpleThread *threadBase() { return thread; } 572 573 InstResult unverifiedResult; 574 RequestPtr unverifiedReq; 575 uint8_t *unverifiedMemData; 576 577 bool changedPC; 578 bool willChangePC; 579 TheISA::PCState newPCState; 580 bool exitOnError; 581 bool updateOnError; 582 bool warnOnlyOnLoadError; 583 584 InstSeqNum youngestSN; 585}; 586 587/** 588 * Templated Checker class. This Checker class is templated on the 589 * DynInstPtr of the instruction type that will be verified. Proper 590 * template instantiations of the Checker must be placed at the bottom 591 * of checker/cpu.cc. 592 */ 593template <class Impl> 594class Checker : public CheckerCPU 595{ 596 private: 597 typedef typename Impl::DynInstPtr DynInstPtr; 598 599 public: 600 Checker(Params *p) 601 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL) 602 { } 603 604 void switchOut(); 605 void takeOverFrom(BaseCPU *oldCPU); 606 607 void advancePC(const Fault &fault); 608 609 void verify(const DynInstPtr &inst); 610 611 void validateInst(const DynInstPtr &inst); 612 void validateExecution(const DynInstPtr &inst); 613 void validateState(); 614 615 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val, 616 int start_idx); 617 void handlePendingInt(); 618 619 private: 620 void handleError(const DynInstPtr &inst) 621 { 622 if (exitOnError) { 623 dumpAndExit(inst); 624 } else if (updateOnError) { 625 updateThisCycle = true; 626 } 627 } 628 629 void dumpAndExit(const DynInstPtr &inst); 630 631 bool updateThisCycle; 632 633 DynInstPtr unverifiedInst; 634 635 std::list<DynInstPtr> instList; 636 typedef typename std::list<DynInstPtr>::iterator InstListIt; 637 void dumpInsts(); 638}; 639 640#endif // __CPU_CHECKER_CPU_HH__ 641