gem5 [DEVELOP-FOR-25.0]
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
179 if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
180 // increment thread level and core level numInsts count
181 commitStats[t_info.thread->threadId()]->numInsts++;
182 baseStats.numInsts++;
183 }
184 // increment thread level numOps count
185 commitStats[t_info.thread->threadId()]->numOps++;
186}
187
190{
191 Counter total_inst = 0;
192 for (auto& t_info : threadInfo) {
193 total_inst += t_info->numInst;
194 }
195
196 return total_inst;
197}
198
201{
202 Counter total_op = 0;
203 for (auto& t_info : threadInfo) {
204 total_op += t_info->numOp;
205 }
206
207 return total_op;
208}
209
213
214void
216{
217 // for now, these are equivalent
218 suspendContext(thread_num);
220}
221
222void
224{
226 for (auto &thread_info : threadInfo) {
227 thread_info->execContextStats.notIdleFraction = (_status != Idle);
228 }
229}
230
231void
233{
234 assert(_status == Idle || _status == Running);
235
236 threadInfo[tid]->thread->serialize(cp);
237}
238
239void
241{
242 threadInfo[tid]->thread->unserialize(cp);
243}
244
245void
249
250void
252{
253 getCpuAddrMonitor(tid)->gotWakeup = true;
254
255 if (threadInfo[tid]->thread->status() == ThreadContext::Suspended) {
256 DPRINTF(Quiesce,"[tid:%d] Suspended Processor awoke\n", tid);
257 threadInfo[tid]->thread->activate();
258 }
259}
260
261void
263{
264 if (debug::ExecFaulting) {
265 traceData->setFaulting(true);
266 } else {
267 delete traceData;
268 traceData = NULL;
269 }
270}
271
272void
274{
276 SimpleThread* thread = t_info.thread;
277 ThreadContext* tc = thread->getTC();
278
280 Fault interrupt = interrupts[curThread]->getInterrupt();
281
282 if (interrupt != NoFault) {
283 // hardware transactional memory
284 // Postpone taking interrupts while executing transactions.
285 assert(!std::dynamic_pointer_cast<GenericHtmFailureFault>(
286 interrupt));
287 if (t_info.inHtmTransactionalState()) {
288 DPRINTF(HtmCpu, "Deferring pending interrupt - %s -"
289 "due to transactional state\n",
290 interrupt->name());
291 return;
292 }
293
294 t_info.fetchOffset = 0;
295 interrupts[curThread]->updateIntrInfo();
296 interrupt->invoke(tc);
297 thread->decoder->reset();
298 }
299 }
300}
301
302
303void
305{
307 SimpleThread* thread = t_info.thread;
308
309 auto &decoder = thread->decoder;
310 Addr instAddr = thread->pcState().instAddr();
311 Addr fetchPC = (instAddr & decoder->pcMask()) + t_info.fetchOffset;
312
313 // set up memory request for instruction fetch
314 DPRINTF(Fetch, "Fetch: Inst PC:%08p, Fetch PC:%08p\n", instAddr, fetchPC);
315
316 req->setVirt(fetchPC, decoder->moreBytesSize(), Request::INST_FETCH,
317 instRequestorId(), instAddr);
318}
319
320void
326
327void
329{
331 SimpleThread* thread = t_info.thread;
332
333 // resets predicates
334 t_info.setPredicate(true);
335 t_info.setMemAccPredicate(true);
336
337 // decode the instruction
338 set(preExecuteTempPC, thread->pcState());
339 auto &pc_state = *preExecuteTempPC;
340
341 auto &decoder = thread->decoder;
342
343 if (isRomMicroPC(pc_state.microPC())) {
344 t_info.stayAtPC = false;
345 curStaticInst = decoder->fetchRomMicroop(
346 pc_state.microPC(), curMacroStaticInst);
347 } else if (!curMacroStaticInst) {
348 //We're not in the middle of a macro instruction
349 StaticInstPtr instPtr = NULL;
350
351 //Predecode, ie bundle up an ExtMachInst
352 //If more fetch data is needed, pass it in.
353 Addr fetch_pc =
354 (pc_state.instAddr() & decoder->pcMask()) + t_info.fetchOffset;
355
356 decoder->moreBytes(pc_state, fetch_pc);
357
358 //Decode an instruction if one is ready. Otherwise, we'll have to
359 //fetch beyond the MachInst at the current pc.
360 instPtr = decoder->decode(pc_state);
361 if (instPtr) {
362 t_info.stayAtPC = false;
363 thread->pcState(pc_state);
364 } else {
365 t_info.stayAtPC = true;
366 t_info.fetchOffset += decoder->moreBytesSize();
367 }
368
369 //If we decoded an instruction and it's microcoded, start pulling
370 //out micro ops
371 if (instPtr && instPtr->isMacroop()) {
372 curMacroStaticInst = instPtr;
374 curMacroStaticInst->fetchMicroop(pc_state.microPC());
375 } else {
376 curStaticInst = instPtr;
377 }
378 } else {
379 //Read the next micro op from the macro op
380 curStaticInst = curMacroStaticInst->fetchMicroop(pc_state.microPC());
381 }
382
383 //If we decoded an instruction this "tick", record information about it.
384 if (curStaticInst) {
385#if TRACING_ON
386 traceData = tracer->getInstRecord(curTick(), thread->getTC(),
388#endif // TRACING_ON
389 }
390
391 if (branchPred && curStaticInst &&
392 curStaticInst->isControl()) {
393 // Use a fake sequence number since we only have one
394 // instruction in flight at the same time.
395 const InstSeqNum cur_sn(0);
396 set(t_info.predPC, thread->pcState());
397 const bool predict_taken(
398 branchPred->predict(curStaticInst, cur_sn, *t_info.predPC,
399 curThread));
400
401 if (predict_taken)
403 }
404
405 // increment the fetch instruction stat counters
406 if (curStaticInst) {
408 }
409}
410
411void
413{
415
416 assert(curStaticInst);
417
418 Addr instAddr = threadContexts[curThread]->pcState().instAddr();
419
420 if (curStaticInst->isMemRef()) {
421 executeStats[t_info.thread->threadId()]->numMemRefs++;
422 }
423
424 if (curStaticInst->isLoad()) {
425 ++t_info.numLoad;
426 }
427
428 if (curStaticInst->isControl()) {
429 ++fetchStats[t_info.thread->threadId()]->numBranches;
430 }
431
432 /* Power model statistics */
433 //integer alu accesses
434 if (curStaticInst->isInteger()){
435 executeStats[t_info.thread->threadId()]->numIntAluAccesses++;
436 commitStats[t_info.thread->threadId()]->numIntInsts++;
437 }
438
439 //float alu accesses
440 if (curStaticInst->isFloating()){
441 executeStats[t_info.thread->threadId()]->numFpAluAccesses++;
442 commitStats[t_info.thread->threadId()]->numFpInsts++;
443 }
444
445 //vector alu accesses
446 if (curStaticInst->isVector()){
447 executeStats[t_info.thread->threadId()]->numVecAluAccesses++;
448 commitStats[t_info.thread->threadId()]->numVecInsts++;
449 }
450
451 //Matrix alu accesses
452 if (curStaticInst->isMatrix()){
455 }
456
457 //number of function calls/returns to get window accesses
458 if (curStaticInst->isCall() || curStaticInst->isReturn()){
460 }
461
462 //result bus acceses
463 if (curStaticInst->isLoad()){
464 commitStats[t_info.thread->threadId()]->numLoadInsts++;
465 }
466
467 if (curStaticInst->isStore() || curStaticInst->isAtomic()){
468 commitStats[t_info.thread->threadId()]->numStoreInsts++;
469 }
470 /* End power model statistics */
471
472 commitStats[t_info.thread->threadId()]
473 ->committedInstType[curStaticInst->opClass()]++;
474 commitStats[t_info.thread->threadId()]->updateComCtrlStats(curStaticInst);
475
476 /* increment the committed numInsts and numOps stats */
478
479 if (FullSystem)
480 traceFunctions(instAddr);
481
482 if (traceData) {
483 traceData->dump();
484 delete traceData;
485 traceData = NULL;
486 }
487
488 // Call CPU instruction commit probes
490}
491
492void
494{
496 SimpleThread* thread = t_info.thread;
497
498 const bool branching = thread->pcState().branching();
499
500 //Since we're moving to a new pc, zero out the offset
501 t_info.fetchOffset = 0;
502 if (fault != NoFault) {
504 fault->invoke(threadContexts[curThread], curStaticInst);
505 thread->decoder->reset();
506 } else {
507 if (curStaticInst) {
508 if (curStaticInst->isLastMicroop())
510 curStaticInst->advancePC(thread);
511 }
512 }
513
514 if (branchPred && curStaticInst && curStaticInst->isControl()) {
515 // Use a fake sequence number since we only have one
516 // instruction in flight at the same time.
517 const InstSeqNum cur_sn(0);
518
519 if (*t_info.predPC != thread->pcState()) {
520
521 // Mis-predicted branch
522 branchPred->squash(cur_sn, thread->pcState(), branching,
523 curThread);
525 }
526 // Update the branch predictor, this is done whether the
527 // prediction was correct or not.
528 branchPred->update(cur_sn, curThread);
529 }
530}
531
532} // 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:220
trace::InstTracer * tracer
Definition base.hh:289
AddressMonitor * getCpuAddrMonitor(ThreadID tid)
Definition base.hh:683
void updateCycleCounters(CPUState state)
base method keeping track of cycle progression
Definition base.hh:588
@ CPU_STATE_SLEEP
Definition base.hh:579
std::vector< std::unique_ptr< CommitCPUStats > > commitStats
Definition base.hh:848
virtual void suspendContext(ThreadID thread_num)
Notify the CPU that the indicated context is now suspended.
Definition base.cc:567
gem5::BaseCPU::BaseCPUStats baseStats
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
Definition base.hh:417
std::vector< std::unique_ptr< ExecuteCPUStats > > executeStats
Definition base.hh:847
bool checkInterrupts(ThreadID tid) const
Definition base.hh:279
std::vector< BaseInterrupts * > interrupts
Definition base.hh:249
void traceFunctions(Addr pc)
Definition base.hh:628
std::vector< std::unique_ptr< FetchCPUStats > > fetchStats
Definition base.hh:846
std::vector< ThreadContext * > threadContexts
Definition base.hh:285
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:400
void preExecute()
Definition base.cc:328
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:232
void resetStats() override
Callback to reset stats.
Definition base.cc:223
branch_prediction::BPredUnit * branchPred
Definition base.hh:87
virtual ~BaseSimpleCPU()
Definition base.cc:210
ThreadID curThread
Definition base.hh:86
void unserializeThread(CheckpointIn &cp, ThreadID tid) override
Unserialize one thread.
Definition base.cc:240
void wakeup(ThreadID tid) override
Definition base.cc:251
StaticInstPtr curMacroStaticInst
Definition base.hh:105
void checkForInterrupts()
Definition base.cc:273
void traceFault()
Handler used when encountering a fault; its purpose is to tear down the InstRecord.
Definition base.cc:262
void advancePC(const Fault &fault)
Definition base.cc:493
void swapActiveThread()
Definition base.cc:135
void setupFetchRequest(const RequestPtr &req)
Definition base.cc:304
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:200
StaticInstPtr curStaticInst
Current instruction.
Definition base.hh:104
Counter totalInsts() const override
Definition base.cc:189
void haltContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now halted.
Definition base.cc:215
void postExecute()
Definition base.cc:412
void countCommitInst()
Definition base.cc:175
trace::InstRecord * traceData
Definition base.hh:97
void countFetchInst()
Definition base.cc:162
void serviceInstCountEvents()
Definition base.cc:321
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
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
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:246
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.

Generated on Mon May 26 2025 09:19:07 for gem5 by doxygen 1.13.2