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