gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
base.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2012, 2015, 2017, 2018, 2020 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) 2002-2005 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
42#include "cpu/simple/base.hh"
43
45#include "base/cprintf.hh"
46#include "base/inifile.hh"
47#include "base/loader/symtab.hh"
48#include "base/logging.hh"
49#include "base/pollevent.hh"
50#include "base/trace.hh"
51#include "base/types.hh"
52#include "cpu/base.hh"
53#include "cpu/checker/cpu.hh"
55#include "cpu/exetrace.hh"
59#include "cpu/simple_thread.hh"
60#include "cpu/smt.hh"
61#include "cpu/static_inst.hh"
62#include "cpu/thread_context.hh"
63#include "debug/Decode.hh"
64#include "debug/ExecFaulting.hh"
65#include "debug/Fetch.hh"
66#include "debug/HtmCpu.hh"
67#include "debug/Quiesce.hh"
68#include "mem/packet.hh"
69#include "mem/request.hh"
70#include "params/BaseSimpleCPU.hh"
71#include "sim/byteswap.hh"
72#include "sim/debug.hh"
73#include "sim/faults.hh"
74#include "sim/full_system.hh"
75#include "sim/sim_events.hh"
76#include "sim/sim_object.hh"
77#include "sim/stats.hh"
78#include "sim/system.hh"
79
80namespace gem5
81{
82
83BaseSimpleCPU::BaseSimpleCPU(const BaseSimpleCPUParams &p)
84 : BaseCPU(p),
85 curThread(0),
87 traceData(NULL),
89{
90 SimpleThread *thread;
91
92 for (unsigned i = 0; i < numThreads; i++) {
93 if (FullSystem) {
94 thread = new SimpleThread(
95 this, i, p.system, p.mmu, p.isa[i], p.decoder[i]);
96 } else {
97 thread = new SimpleThread(
98 this, i, p.system, p.workload[i], p.mmu, p.isa[i],
99 p.decoder[i]);
100 }
101 threadInfo.push_back(new SimpleExecContext(this, thread));
102 ThreadContext *tc = thread->getTC();
103 threadContexts.push_back(tc);
104 }
105
106 if (p.checker) {
107 if (numThreads != 1)
108 fatal("Checker currently does not support SMT");
109
110 BaseCPU *temp_checker = p.checker;
111 checker = dynamic_cast<CheckerCPU *>(temp_checker);
112 checker->setSystem(p.system);
113 // Manipulate thread context
114 ThreadContext *cpu_tc = threadContexts[0];
115 threadContexts[0] = new CheckerThreadContext<ThreadContext>(
116 cpu_tc, this->checker);
117 } else {
118 checker = NULL;
119 }
120}
121
122void
124{
125 Addr oldpc, pc = threadInfo[curThread]->thread->pcState().instAddr();
126 do {
127 oldpc = pc;
128 threadInfo[curThread]->thread->pcEventQueue.service(
129 oldpc, threadContexts[curThread]);
130 pc = threadInfo[curThread]->thread->pcState().instAddr();
131 } while (oldpc != pc);
132}
133
134void
136{
137 if (numThreads > 1) {
138 if ((!curStaticInst || !curStaticInst->isDelayedCommit()) &&
139 !threadInfo[curThread]->stayAtPC) {
140 // Swap active threads
141 if (!activeThreads.empty()) {
142 curThread = activeThreads.front();
143 activeThreads.pop_front();
144 activeThreads.push_back(curThread);
145 }
146 }
147 }
148}
149
150void
152{
154
155 if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
156 t_info.numInst++;
157 }
158 t_info.numOp++;
159}
160
161void
163{
165
166 if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
167 // increment thread level numInsts fetched count
168 fetchStats[t_info.thread->threadId()]->numInsts++;
169 }
170 // increment thread level numOps fetched count
171 fetchStats[t_info.thread->threadId()]->numOps++;
172}
173
174void
176{
178 bool is_nop = curStaticInst->isNop();
179 const ThreadID tid = t_info.thread->threadId();
180 const bool in_user_mode = t_info.thread->getIsaPtr()->inUserMode();
181
182 if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
183 // increment thread level and core level numInsts count
184 commitStats[tid]->numInsts++;
185 baseStats.numInsts++;
186 t_info.thread->threadStats.numInsts++;
187 executeStats[tid]->numInsts++;
188 if (!is_nop) {
189 commitStats[tid]->numInstsNotNOP++;
190 }
191 if (in_user_mode) {
192 commitStats[tid]->numUserInsts++;
193 }
194 }
195
196 // increment thread level numOps count
197 t_info.thread->threadStats.numOps++;
198 if (!is_nop) {
199 commitStats[t_info.thread->threadId()]->numOpsNotNOP++;
200 }
201 commitStats[tid]->numOps++;
202 if (in_user_mode) {
203 commitStats[tid]->numUserOps++;
204 }
205}
206
209{
210 Counter total_inst = 0;
211 for (auto& t_info : threadInfo) {
212 total_inst += t_info->numInst;
213 }
214
215 return total_inst;
216}
217
220{
221 Counter total_op = 0;
222 for (auto& t_info : threadInfo) {
223 total_op += t_info->numOp;
224 }
225
226 return total_op;
227}
228
232
233void
235{
236 // for now, these are equivalent
237 suspendContext(thread_num);
239}
240
241void
243{
245 for (auto &thread_info : threadInfo) {
246 thread_info->execContextStats.notIdleFraction = (_status != Idle);
247 }
248}
249
250void
252{
253 assert(_status == Idle || _status == Running);
254
255 threadInfo[tid]->thread->serialize(cp);
256}
257
258void
260{
261 threadInfo[tid]->thread->unserialize(cp);
262}
263
264void
268
269void
271{
272 getCpuAddrMonitor(tid)->gotWakeup = true;
273
274 if (threadInfo[tid]->thread->status() == ThreadContext::Suspended) {
275 DPRINTF(Quiesce,"[tid:%d] Suspended Processor awoke\n", tid);
276 threadInfo[tid]->thread->activate();
277 }
278}
279
280void
282{
283 if (debug::ExecFaulting) {
284 traceData->setFaulting(true);
285 } else {
286 delete traceData;
287 traceData = NULL;
288 }
289}
290
291void
293{
295 SimpleThread* thread = t_info.thread;
296 ThreadContext* tc = thread->getTC();
297
299 Fault interrupt = interrupts[curThread]->getInterrupt();
300
301 if (interrupt != NoFault) {
302 // hardware transactional memory
303 // Postpone taking interrupts while executing transactions.
304 assert(!std::dynamic_pointer_cast<GenericHtmFailureFault>(
305 interrupt));
306 if (t_info.inHtmTransactionalState()) {
307 DPRINTF(HtmCpu, "Deferring pending interrupt - %s -"
308 "due to transactional state\n",
309 interrupt->name());
310 return;
311 }
312
313 t_info.fetchOffset = 0;
314 interrupts[curThread]->updateIntrInfo();
315 interrupt->invoke(tc);
316 thread->decoder->reset();
317 }
318 }
319}
320
321
322void
324{
326 SimpleThread* thread = t_info.thread;
327
328 auto &decoder = thread->decoder;
329 Addr instAddr = thread->pcState().instAddr();
330 Addr fetchPC = (instAddr & decoder->pcMask()) + t_info.fetchOffset;
331
332 // set up memory request for instruction fetch
333 DPRINTF(Fetch, "Fetch: Inst PC:%08p, Fetch PC:%08p\n", instAddr, fetchPC);
334
335 req->setVirt(fetchPC, decoder->moreBytesSize(), Request::INST_FETCH,
336 instRequestorId(), instAddr);
337}
338
339void
345
346void
348{
350 SimpleThread* thread = t_info.thread;
351
352 // resets predicates
353 t_info.setPredicate(true);
354 t_info.setMemAccPredicate(true);
355
356 // decode the instruction
357 set(preExecuteTempPC, thread->pcState());
358 auto &pc_state = *preExecuteTempPC;
359
360 auto &decoder = thread->decoder;
361
362 if (isRomMicroPC(pc_state.microPC())) {
363 t_info.stayAtPC = false;
364 curStaticInst = decoder->fetchRomMicroop(
365 pc_state.microPC(), curMacroStaticInst);
366 } else if (!curMacroStaticInst) {
367 //We're not in the middle of a macro instruction
368 StaticInstPtr instPtr = NULL;
369
370 //Predecode, ie bundle up an ExtMachInst
371 //If more fetch data is needed, pass it in.
372 Addr fetch_pc =
373 (pc_state.instAddr() & decoder->pcMask()) + t_info.fetchOffset;
374
375 decoder->moreBytes(pc_state, fetch_pc);
376
377 //Decode an instruction if one is ready. Otherwise, we'll have to
378 //fetch beyond the MachInst at the current pc.
379 instPtr = decoder->decode(pc_state);
380 if (instPtr) {
381 t_info.stayAtPC = false;
382 thread->pcState(pc_state);
383 } else {
384 t_info.stayAtPC = true;
385 t_info.fetchOffset += decoder->moreBytesSize();
386 }
387
388 //If we decoded an instruction and it's microcoded, start pulling
389 //out micro ops
390 if (instPtr && instPtr->isMacroop()) {
391 curMacroStaticInst = instPtr;
393 curMacroStaticInst->fetchMicroop(pc_state.microPC());
394 } else {
395 curStaticInst = instPtr;
396 }
397 } else {
398 //Read the next micro op from the macro op
399 curStaticInst = curMacroStaticInst->fetchMicroop(pc_state.microPC());
400 }
401
402 //If we decoded an instruction this "tick", record information about it.
403 if (curStaticInst) {
404#if TRACING_ON
405 traceData = tracer->getInstRecord(curTick(), thread->getTC(),
407#endif // TRACING_ON
408 }
409
410 if (branchPred && curStaticInst &&
411 curStaticInst->isControl()) {
412 // Use a fake sequence number since we only have one
413 // instruction in flight at the same time.
414 const InstSeqNum cur_sn(0);
415 set(t_info.predPC, thread->pcState());
416 const bool predict_taken(
417 branchPred->predict(curStaticInst, cur_sn, *t_info.predPC,
418 curThread));
419
420 if (predict_taken)
422 }
423
424 // increment the fetch instruction stat counters
425 if (curStaticInst) {
427 }
428}
429
430void
432{
434
435 assert(curStaticInst);
436
437 Addr instAddr = threadContexts[curThread]->pcState().instAddr();
438 auto op_class = curStaticInst->opClass();
439 t_info.issueStats.issuedInstType[curThread][op_class]++;
440
441 if (curStaticInst->isMemRef()) {
442 executeStats[t_info.thread->threadId()]->numMemRefs++;
443 commitStats[t_info.thread->threadId()]->numMemRefs++;
444 t_info.thread->threadStats.numMemRefs++;
445 }
446
447 if (curStaticInst->isLoad()) {
448 ++t_info.numLoad;
449 }
450
451 if (curStaticInst->isControl()) {
452 ++fetchStats[t_info.thread->threadId()]->numBranches;
453 }
454
455 /* Power model statistics */
456 //integer alu accesses
457 if (curStaticInst->isInteger()){
458 executeStats[t_info.thread->threadId()]->numIntAluAccesses++;
459 commitStats[t_info.thread->threadId()]->numIntInsts++;
460 }
461
462 //float alu accesses
463 if (curStaticInst->isFloating()){
464 executeStats[t_info.thread->threadId()]->numFpAluAccesses++;
465 commitStats[t_info.thread->threadId()]->numFpInsts++;
466 }
467
468 //vector alu accesses
469 if (curStaticInst->isVector()){
470 executeStats[t_info.thread->threadId()]->numVecAluAccesses++;
471 commitStats[t_info.thread->threadId()]->numVecInsts++;
472 }
473
474 //Matrix alu accesses
475 if (curStaticInst->isMatrix()){
478 }
479
480 //number of function calls/returns to get window accesses
481 if (curStaticInst->isCall() || curStaticInst->isReturn()){
482 commitStats[t_info.thread->threadId()]->numCallsReturns++;
483 }
484
485 // same as above, but *just* calls
486 if (curStaticInst->isCall()) {
487 commitStats[t_info.thread->threadId()]->functionCalls++;
488 }
489 if (curStaticInst->isControl()) {
490 executeStats[t_info.thread->threadId()]->numBranches++;
491 }
492
493 //result bus acceses
494 if (curStaticInst->isLoad()){
495 commitStats[t_info.thread->threadId()]->numLoadInsts++;
496 executeStats[t_info.thread->threadId()]->numLoadInsts++;
497 }
498
499 if (curStaticInst->isStore() || curStaticInst->isAtomic()){
500 commitStats[t_info.thread->threadId()]->numStoreInsts++;
501 }
502 /* End power model statistics */
503
504 commitStats[t_info.thread->threadId()]->committedInstType[op_class]++;
505 commitStats[t_info.thread->threadId()]->updateComCtrlStats(curStaticInst);
506
507 /* increment the committed numInsts and numOps stats */
509
510 if (FullSystem)
511 traceFunctions(instAddr);
512
513 if (traceData) {
514 traceData->dump();
515 delete traceData;
516 traceData = NULL;
517 }
518
519 // Call CPU instruction commit probes
521}
522
523void
525{
527 SimpleThread* thread = t_info.thread;
528
529 const bool branching = thread->pcState().branching();
530
531 //Since we're moving to a new pc, zero out the offset
532 t_info.fetchOffset = 0;
533 if (fault != NoFault) {
535 fault->invoke(threadContexts[curThread], curStaticInst);
536 thread->decoder->reset();
537 } else {
538 if (curStaticInst) {
539 if (curStaticInst->isLastMicroop())
541 curStaticInst->advancePC(thread);
542 }
543 }
544
545 if (branchPred && curStaticInst && curStaticInst->isControl()) {
546 // Use a fake sequence number since we only have one
547 // instruction in flight at the same time.
548 const InstSeqNum cur_sn(0);
549
550 if (*t_info.predPC != thread->pcState()) {
551
552 // Mis-predicted branch
553 branchPred->squash(cur_sn, thread->pcState(), branching,
554 curThread);
556 }
557 // Update the branch predictor, this is done whether the
558 // prediction was correct or not.
559 branchPred->update(cur_sn, curThread);
560 }
561}
562
563} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
RequestorID instRequestorId() const
Reads this CPU's unique instruction requestor ID.
Definition base.hh:221
trace::InstTracer * tracer
Definition base.hh:290
AddressMonitor * getCpuAddrMonitor(ThreadID tid)
Definition base.hh:680
void updateCycleCounters(CPUState state)
base method keeping track of cycle progression
Definition base.hh:585
@ CPU_STATE_SLEEP
Definition base.hh:576
std::vector< std::unique_ptr< CommitCPUStats > > commitStats
Definition base.hh:860
virtual void suspendContext(ThreadID thread_num)
Notify the CPU that the indicated context is now suspended.
Definition base.cc:577
gem5::BaseCPU::BaseCPUStats baseStats
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition base.hh:414
std::vector< std::unique_ptr< ExecuteCPUStats > > executeStats
Definition base.hh:859
bool checkInterrupts(ThreadID tid) const
Definition base.hh:280
std::vector< BaseInterrupts * > interrupts
Definition base.hh:250
void traceFunctions(Addr pc)
Definition base.hh:625
std::vector< std::unique_ptr< FetchCPUStats > > fetchStats
Definition base.hh:858
std::vector< ThreadContext * > threadContexts
Definition base.hh:286
BaseCPU(const Params &params, bool is_checker=false)
Definition base.cc:129
virtual void probeInstCommit(const StaticInstPtr &inst, Addr pc)
Helper method to trigger PMU probes for a committed instruction.
Definition base.cc:410
virtual bool inUserMode() const =0
void preExecute()
Definition base.cc:347
void checkPcEventQueue()
Definition base.cc:123
BaseSimpleCPU(const BaseSimpleCPUParams &params)
Definition base.cc:83
void serializeThread(CheckpointOut &cp, ThreadID tid) const override
Serialize a single thread.
Definition base.cc:251
void resetStats() override
Callback to reset stats.
Definition base.cc:242
branch_prediction::BPredUnit * branchPred
Definition base.hh:87
virtual ~BaseSimpleCPU()
Definition base.cc:229
ThreadID curThread
Definition base.hh:86
void unserializeThread(CheckpointIn &cp, ThreadID tid) override
Unserialize one thread.
Definition base.cc:259
void wakeup(ThreadID tid) override
Definition base.cc:270
StaticInstPtr curMacroStaticInst
Definition base.hh:105
void checkForInterrupts()
Definition base.cc:292
void traceFault()
Handler used when encountering a fault; its purpose is to tear down the InstRecord.
Definition base.cc:281
void advancePC(const Fault &fault)
Definition base.cc:524
void swapActiveThread()
Definition base.cc:135
void setupFetchRequest(const RequestPtr &req)
Definition base.cc:323
std::unique_ptr< PCStateBase > preExecuteTempPC
Definition base.hh:133
std::list< ThreadID > activeThreads
Definition base.hh:101
std::vector< SimpleExecContext * > threadInfo
Definition base.hh:100
Counter totalOps() const override
Definition base.cc:219
StaticInstPtr curStaticInst
Current instruction.
Definition base.hh:104
Counter totalInsts() const override
Definition base.cc:208
void haltContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now halted.
Definition base.cc:234
void postExecute()
Definition base.cc:431
void countCommitInst()
Definition base.cc:175
trace::InstRecord * traceData
Definition base.hh:97
void countFetchInst()
Definition base.cc:162
void serviceInstCountEvents()
Definition base.cc:340
virtual void reset()
Definition decoder.hh:63
virtual bool branching() const =0
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
@ INST_FETCH
The request was an instruction fetch.
Definition request.hh:115
Counter numInst
PER-THREAD STATS.
void setMemAccPredicate(bool val) override
void setPredicate(bool val) override
std::unique_ptr< PCStateBase > predPC
bool inHtmTransactionalState() const override
gem5::SimpleExecContext::ExecContextStats execContextStats
gem5::SimpleExecContext::IssueStats issueStats
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
int threadId() const override
EventQueue comInstEventQueue
An instruction-based event queue.
const PCStateBase & pcState() const override
ThreadContext * getTC()
Returns the pointer to this SimpleThread's ThreadContext.
InstDecoder * decoder
BaseISA * getIsaPtr() const override
bool isMacroop() const
ThreadContext is the external interface to all thread state for anything outside of the CPU.
@ Suspended
Temporarily inactive.
void serviceEvents(Tick when)
process all events up to the given timestamp.
Definition eventq.hh:869
virtual void resetStats()
Callback to reset stats.
Definition group.cc:86
Declaration of IniFile object.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 3, 0 > priority
Bitfield< 4 > pc
Bitfield< 0 > p
double Counter
All counters are of 64-bit values.
Definition types.hh:46
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
static void activate(const char *expr)
Definition debug.cc:71
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
RefCountingPtr< StaticInst > StaticInstPtr
static bool isRomMicroPC(MicroPC upc)
Definition types.hh:166
void change_thread_state(ThreadID tid, int activate, int priority)
Changes the status and priority of the thread with the given number.
Definition base.cc:265
const StaticInstPtr nullStaticInstPtr
Statically allocated null StaticInstPtr.
constexpr decltype(nullptr) NoFault
Definition types.hh:253
uint64_t InstSeqNum
Definition inst_seq.hh:40
output decoder
Definition nop.cc:61
Declaration of the Packet class.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
Defines SMT_MAX_THREADS.
statistics::Scalar numBranchMispred
Number of misprediced branches.
statistics::Scalar numOps
Stat for number ops (including micro ops) committed.
statistics::Scalar numMemRefs
Stat for number of memory references.
statistics::Scalar numInsts
Stat for number instructions committed.
gem5::ThreadState::ThreadStateStats threadStats

Generated on Mon Oct 27 2025 04:13:00 for gem5 by doxygen 1.14.0