1/* 2 * Copyright (c) 2014-2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2002-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Kevin Lim 41 * Andreas Sandberg 42 * Mitch Hayenga 43 */ 44 45#ifndef __CPU_SIMPLE_EXEC_CONTEXT_HH__ 46#define __CPU_SIMPLE_EXEC_CONTEXT_HH__ 47 48#include "arch/registers.hh" 49#include "base/types.hh" 50#include "config/the_isa.hh" 51#include "cpu/base.hh" 52#include "cpu/exec_context.hh" 53#include "cpu/reg_class.hh" 54#include "cpu/simple/base.hh" 55#include "cpu/static_inst_fwd.hh" 56#include "cpu/translation.hh" 57#include "mem/request.hh" 58 59class BaseSimpleCPU; 60 61class SimpleExecContext : public ExecContext { 62 protected: 63 using VecRegContainer = TheISA::VecRegContainer; 64 using VecElem = TheISA::VecElem; 65 66 public: 67 BaseSimpleCPU *cpu; 68 SimpleThread* thread; 69 70 // This is the offset from the current pc that fetch should be performed 71 Addr fetchOffset; 72 // This flag says to stay at the current pc. This is useful for 73 // instructions which go beyond MachInst boundaries. 74 bool stayAtPC; 75 76 // Branch prediction 77 TheISA::PCState predPC; 78 79 /** PER-THREAD STATS */ 80 81 // Number of simulated instructions 82 Counter numInst; 83 Stats::Scalar numInsts; 84 Counter numOp; 85 Stats::Scalar numOps; 86 87 // Number of integer alu accesses 88 Stats::Scalar numIntAluAccesses; 89 90 // Number of float alu accesses 91 Stats::Scalar numFpAluAccesses; 92 93 // Number of vector alu accesses 94 Stats::Scalar numVecAluAccesses; 95 96 // Number of function calls/returns 97 Stats::Scalar numCallsReturns; 98 99 // Conditional control instructions; 100 Stats::Scalar numCondCtrlInsts; 101 102 // Number of int instructions 103 Stats::Scalar numIntInsts; 104 105 // Number of float instructions 106 Stats::Scalar numFpInsts; 107 108 // Number of vector instructions 109 Stats::Scalar numVecInsts; 110 111 // Number of integer register file accesses 112 Stats::Scalar numIntRegReads; 113 Stats::Scalar numIntRegWrites; 114 115 // Number of float register file accesses 116 Stats::Scalar numFpRegReads; 117 Stats::Scalar numFpRegWrites; 118 119 // Number of vector register file accesses 120 mutable Stats::Scalar numVecRegReads; 121 Stats::Scalar numVecRegWrites; 122 123 // Number of predicate register file accesses 124 mutable Stats::Scalar numVecPredRegReads; 125 Stats::Scalar numVecPredRegWrites; 126 127 // Number of condition code register file accesses 128 Stats::Scalar numCCRegReads; 129 Stats::Scalar numCCRegWrites; 130 131 // Number of simulated memory references 132 Stats::Scalar numMemRefs; 133 Stats::Scalar numLoadInsts; 134 Stats::Scalar numStoreInsts; 135 136 // Number of idle cycles 137 Stats::Formula numIdleCycles; 138 139 // Number of busy cycles 140 Stats::Formula numBusyCycles; 141 142 // Number of simulated loads 143 Counter numLoad; 144 145 // Number of idle cycles 146 Stats::Average notIdleFraction; 147 Stats::Formula idleFraction; 148 149 // Number of cycles stalled for I-cache responses 150 Stats::Scalar icacheStallCycles; 151 Counter lastIcacheStall; 152 153 // Number of cycles stalled for D-cache responses 154 Stats::Scalar dcacheStallCycles; 155 Counter lastDcacheStall; 156 157 /// @{ 158 /// Total number of branches fetched 159 Stats::Scalar numBranches; 160 /// Number of branches predicted as taken 161 Stats::Scalar numPredictedBranches; 162 /// Number of misprediced branches 163 Stats::Scalar numBranchMispred; 164 /// @} 165 166 // Instruction mix histogram by OpClass 167 Stats::Vector statExecutedInstType; 168 169 public: 170 /** Constructor */ 171 SimpleExecContext(BaseSimpleCPU* _cpu, SimpleThread* _thread) 172 : cpu(_cpu), thread(_thread), fetchOffset(0), stayAtPC(false), 173 numInst(0), numOp(0), numLoad(0), lastIcacheStall(0), lastDcacheStall(0) 174 { } 175 176 /** Reads an integer register. */ 177 RegVal 178 readIntRegOperand(const StaticInst *si, int idx) override 179 { 180 numIntRegReads++; 181 const RegId& reg = si->srcRegIdx(idx); 182 assert(reg.isIntReg()); 183 return thread->readIntReg(reg.index()); 184 } 185 186 /** Sets an integer register to a value. */ 187 void 188 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override 189 { 190 numIntRegWrites++; 191 const RegId& reg = si->destRegIdx(idx); 192 assert(reg.isIntReg()); 193 thread->setIntReg(reg.index(), val); 194 } 195 196 /** Reads a floating point register in its binary format, instead 197 * of by value. */ 198 RegVal 199 readFloatRegOperandBits(const StaticInst *si, int idx) override 200 { 201 numFpRegReads++; 202 const RegId& reg = si->srcRegIdx(idx); 203 assert(reg.isFloatReg()); 204 return thread->readFloatReg(reg.index()); 205 } 206 207 /** Sets the bits of a floating point register of single width 208 * to a binary value. */ 209 void 210 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override 211 { 212 numFpRegWrites++; 213 const RegId& reg = si->destRegIdx(idx); 214 assert(reg.isFloatReg()); 215 thread->setFloatReg(reg.index(), val); 216 } 217 218 /** Reads a vector register. */ 219 const VecRegContainer & 220 readVecRegOperand(const StaticInst *si, int idx) const override 221 { 222 numVecRegReads++; 223 const RegId& reg = si->srcRegIdx(idx); 224 assert(reg.isVecReg()); 225 return thread->readVecReg(reg); 226 } 227 228 /** Reads a vector register for modification. */ 229 VecRegContainer & 230 getWritableVecRegOperand(const StaticInst *si, int idx) override 231 { 232 numVecRegWrites++; 233 const RegId& reg = si->destRegIdx(idx); 234 assert(reg.isVecReg()); 235 return thread->getWritableVecReg(reg); 236 } 237 238 /** Sets a vector register to a value. */ 239 void 240 setVecRegOperand(const StaticInst *si, int idx, 241 const VecRegContainer& val) override 242 { 243 numVecRegWrites++; 244 const RegId& reg = si->destRegIdx(idx); 245 assert(reg.isVecReg()); 246 thread->setVecReg(reg, val); 247 } 248 249 /** Vector Register Lane Interfaces. */ 250 /** @{ */ 251 /** Reads source vector lane. */ 252 template <typename VecElem> 253 VecLaneT<VecElem, true> 254 readVecLaneOperand(const StaticInst *si, int idx) const 255 { 256 numVecRegReads++; 257 const RegId& reg = si->srcRegIdx(idx); 258 assert(reg.isVecReg()); 259 return thread->readVecLane<VecElem>(reg); 260 } 261 /** Reads source vector 8bit operand. */ 262 virtual ConstVecLane8 263 readVec8BitLaneOperand(const StaticInst *si, int idx) const 264 override 265 { return readVecLaneOperand<uint8_t>(si, idx); } 266 267 /** Reads source vector 16bit operand. */ 268 virtual ConstVecLane16 269 readVec16BitLaneOperand(const StaticInst *si, int idx) const 270 override 271 { return readVecLaneOperand<uint16_t>(si, idx); } 272 273 /** Reads source vector 32bit operand. */ 274 virtual ConstVecLane32 275 readVec32BitLaneOperand(const StaticInst *si, int idx) const 276 override 277 { return readVecLaneOperand<uint32_t>(si, idx); } 278 279 /** Reads source vector 64bit operand. */ 280 virtual ConstVecLane64 281 readVec64BitLaneOperand(const StaticInst *si, int idx) const 282 override 283 { return readVecLaneOperand<uint64_t>(si, idx); } 284 285 /** Write a lane of the destination vector operand. */ 286 template <typename LD> 287 void 288 setVecLaneOperandT(const StaticInst *si, int idx, 289 const LD& val) 290 { 291 numVecRegWrites++; 292 const RegId& reg = si->destRegIdx(idx); 293 assert(reg.isVecReg()); 294 return thread->setVecLane(reg, val); 295 } 296 /** Write a lane of the destination vector operand. */ 297 virtual void 298 setVecLaneOperand(const StaticInst *si, int idx, 299 const LaneData<LaneSize::Byte>& val) override 300 { return setVecLaneOperandT(si, idx, val); } 301 /** Write a lane of the destination vector operand. */ 302 virtual void 303 setVecLaneOperand(const StaticInst *si, int idx, 304 const LaneData<LaneSize::TwoByte>& val) override 305 { return setVecLaneOperandT(si, idx, val); } 306 /** Write a lane of the destination vector operand. */ 307 virtual void 308 setVecLaneOperand(const StaticInst *si, int idx, 309 const LaneData<LaneSize::FourByte>& val) override 310 { return setVecLaneOperandT(si, idx, val); } 311 /** Write a lane of the destination vector operand. */ 312 virtual void 313 setVecLaneOperand(const StaticInst *si, int idx, 314 const LaneData<LaneSize::EightByte>& val) override 315 { return setVecLaneOperandT(si, idx, val); } 316 /** @} */ 317 318 /** Reads an element of a vector register. */ 319 VecElem 320 readVecElemOperand(const StaticInst *si, int idx) const override 321 { 322 numVecRegReads++; 323 const RegId& reg = si->srcRegIdx(idx); 324 assert(reg.isVecElem()); 325 return thread->readVecElem(reg); 326 } 327 328 /** Sets an element of a vector register to a value. */ 329 void 330 setVecElemOperand(const StaticInst *si, int idx, 331 const VecElem val) override 332 { 333 numVecRegWrites++; 334 const RegId& reg = si->destRegIdx(idx); 335 assert(reg.isVecElem()); 336 thread->setVecElem(reg, val); 337 } 338 339 const VecPredRegContainer& 340 readVecPredRegOperand(const StaticInst *si, int idx) const override 341 { 342 numVecPredRegReads++; 343 const RegId& reg = si->srcRegIdx(idx); 344 assert(reg.isVecPredReg()); 345 return thread->readVecPredReg(reg); 346 } 347 348 VecPredRegContainer& 349 getWritableVecPredRegOperand(const StaticInst *si, int idx) override 350 { 351 numVecPredRegWrites++; 352 const RegId& reg = si->destRegIdx(idx); 353 assert(reg.isVecPredReg()); 354 return thread->getWritableVecPredReg(reg); 355 } 356 357 void 358 setVecPredRegOperand(const StaticInst *si, int idx, 359 const VecPredRegContainer& val) override 360 { 361 numVecPredRegWrites++; 362 const RegId& reg = si->destRegIdx(idx); 363 assert(reg.isVecPredReg()); 364 thread->setVecPredReg(reg, val); 365 } 366 367 RegVal 368 readCCRegOperand(const StaticInst *si, int idx) override 369 { 370 numCCRegReads++; 371 const RegId& reg = si->srcRegIdx(idx); 372 assert(reg.isCCReg()); 373 return thread->readCCReg(reg.index()); 374 } 375 376 void 377 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override 378 { 379 numCCRegWrites++; 380 const RegId& reg = si->destRegIdx(idx); 381 assert(reg.isCCReg()); 382 thread->setCCReg(reg.index(), val); 383 } 384 385 RegVal 386 readMiscRegOperand(const StaticInst *si, int idx) override 387 { 388 numIntRegReads++; 389 const RegId& reg = si->srcRegIdx(idx); 390 assert(reg.isMiscReg()); 391 return thread->readMiscReg(reg.index()); 392 } 393 394 void 395 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override 396 { 397 numIntRegWrites++; 398 const RegId& reg = si->destRegIdx(idx); 399 assert(reg.isMiscReg()); 400 thread->setMiscReg(reg.index(), val); 401 } 402 403 /** 404 * Reads a miscellaneous register, handling any architectural 405 * side effects due to reading that register. 406 */ 407 RegVal 408 readMiscReg(int misc_reg) override 409 { 410 numIntRegReads++; 411 return thread->readMiscReg(misc_reg); 412 } 413 414 /** 415 * Sets a miscellaneous register, handling any architectural 416 * side effects due to writing that register. 417 */ 418 void 419 setMiscReg(int misc_reg, RegVal val) override 420 { 421 numIntRegWrites++; 422 thread->setMiscReg(misc_reg, val); 423 } 424 425 PCState 426 pcState() const override 427 { 428 return thread->pcState(); 429 } 430 431 void 432 pcState(const PCState &val) override 433 { 434 thread->pcState(val); 435 } 436 437 Fault 438 readMem(Addr addr, uint8_t *data, unsigned int size, 439 Request::Flags flags, 440 const std::vector<bool>& byteEnable = std::vector<bool>()) 441 override 442 { 443 return cpu->readMem(addr, data, size, flags, byteEnable); 444 } 445 446 Fault 447 initiateMemRead(Addr addr, unsigned int size, 448 Request::Flags flags, 449 const std::vector<bool>& byteEnable = std::vector<bool>()) 450 override 451 { 452 return cpu->initiateMemRead(addr, size, flags, byteEnable); 453 } 454 455 Fault 456 writeMem(uint8_t *data, unsigned int size, Addr addr, 457 Request::Flags flags, uint64_t *res, 458 const std::vector<bool>& byteEnable = std::vector<bool>()) 459 override 460 { 461 assert(byteEnable.empty() || byteEnable.size() == size); 462 return cpu->writeMem(data, size, addr, flags, res, byteEnable); 463 } 464 465 Fault amoMem(Addr addr, uint8_t *data, unsigned int size, 466 Request::Flags flags, AtomicOpFunctorPtr amo_op) override 467 { 468 return cpu->amoMem(addr, data, size, flags, std::move(amo_op)); 469 } 470 471 Fault initiateMemAMO(Addr addr, unsigned int size, 472 Request::Flags flags, 473 AtomicOpFunctorPtr amo_op) override 474 { 475 return cpu->initiateMemAMO(addr, size, flags, std::move(amo_op)); 476 } 477 478 /** 479 * Sets the number of consecutive store conditional failures. 480 */ 481 void 482 setStCondFailures(unsigned int sc_failures) override 483 { 484 thread->setStCondFailures(sc_failures); 485 } 486 487 /** 488 * Returns the number of consecutive store conditional failures. 489 */ 490 unsigned int 491 readStCondFailures() const override 492 { 493 return thread->readStCondFailures(); 494 } 495 496 /** 497 * Executes a syscall specified by the callnum. 498 */ 499 void 500 syscall(int64_t callnum, Fault *fault) override 501 { 502 if (FullSystem) 503 panic("Syscall emulation isn't available in FS mode."); 504 505 thread->syscall(callnum, fault); 506 } 507 508 /** Returns a pointer to the ThreadContext. */ 509 ThreadContext *tcBase() override { return thread->getTC(); } 510 511 bool 512 readPredicate() const override 513 { 514 return thread->readPredicate(); 515 } 516 517 void 518 setPredicate(bool val) override 519 { 520 thread->setPredicate(val); 521 522 if (cpu->traceData) { 523 cpu->traceData->setPredicate(val); 524 } 525 } 526 527 bool 528 readMemAccPredicate() const override 529 { 530 return thread->readMemAccPredicate(); 531 } 532 533 void 534 setMemAccPredicate(bool val) override 535 { 536 thread->setMemAccPredicate(val); 537 } 538 539 /** 540 * Invalidate a page in the DTLB <i>and</i> ITLB. 541 */ 542 void 543 demapPage(Addr vaddr, uint64_t asn) override 544 { 545 thread->demapPage(vaddr, asn); 546 } 547 548 void 549 armMonitor(Addr address) override 550 { 551 cpu->armMonitor(thread->threadId(), address); 552 } 553 554 bool 555 mwait(PacketPtr pkt) override 556 { 557 return cpu->mwait(thread->threadId(), pkt); 558 } 559 560 void 561 mwaitAtomic(ThreadContext *tc) override 562 { 563 cpu->mwaitAtomic(thread->threadId(), tc, thread->dtb); 564 } 565 566 AddressMonitor * 567 getAddrMonitor() override 568 { 569 return cpu->getCpuAddrMonitor(thread->threadId()); 570 } 571}; 572 573#endif // __CPU_EXEC_CONTEXT_HH__ 574