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