1/*
2 * Copyright (c) 2011-2013, 2017 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 * Copyright (c) 2011 Regents of the University of California
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: Steve Reinhardt
42 *          Nathan Binkert
43 *          Rick Strong
44 */
45
46#ifndef __CPU_BASE_HH__
47#define __CPU_BASE_HH__
48
49#include <vector>
50
51// Before we do anything else, check if this build is the NULL ISA,
52// and if so stop here
53#include "config/the_isa.hh"
54#if THE_ISA == NULL_ISA
55#include "arch/null/cpu_dummy.hh"
56#else
57#include "arch/interrupts.hh"
58#include "arch/isa_traits.hh"
59#include "arch/microcode_rom.hh"
60#include "base/statistics.hh"
61#include "sim/clocked_object.hh"
62#include "sim/eventq.hh"
63#include "sim/full_system.hh"
64#include "sim/insttracer.hh"
65#include "sim/probe/pmu.hh"
66#include "sim/probe/probe.hh"
67#include "sim/system.hh"
68#include "debug/Mwait.hh"
69
70class BaseCPU;
71struct BaseCPUParams;
72class CheckerCPU;
73class ThreadContext;
74
75struct AddressMonitor
76{
77    AddressMonitor();
78    bool doMonitor(PacketPtr pkt);
79
80    bool armed;
81    Addr vAddr;
82    Addr pAddr;
83    uint64_t val;
84    bool waiting;   // 0=normal, 1=mwaiting
85    bool gotWakeup;
86};
87
88class CPUProgressEvent : public Event
89{
90  protected:
91    Tick _interval;
92    Counter lastNumInst;
93    BaseCPU *cpu;
94    bool _repeatEvent;
95
96  public:
97    CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);
98
99    void process();
100
101    void interval(Tick ival) { _interval = ival; }
102    Tick interval() { return _interval; }
103
104    void repeatEvent(bool repeat) { _repeatEvent = repeat; }
105
106    virtual const char *description() const;
107};
108
109class BaseCPU : public ClockedObject
110{
111  protected:
112
113    /// Instruction count used for SPARC misc register
114    /// @todo unify this with the counters that cpus individually keep
115    Tick instCnt;
116
117    // every cpu has an id, put it in the base cpu
118    // Set at initialization, only time a cpuId might change is during a
119    // takeover (which should be done from within the BaseCPU anyway,
120    // therefore no setCpuId() method is provided
121    int _cpuId;
122
123    /** Each cpu will have a socket ID that corresponds to its physical location
124     * in the system. This is usually used to bucket cpu cores under single DVFS
125     * domain. This information may also be required by the OS to identify the
126     * cpu core grouping (as in the case of ARM via MPIDR register)
127     */
128    const uint32_t _socketId;
129
130    /** instruction side request id that must be placed in all requests */
131    MasterID _instMasterId;
132
133    /** data side request id that must be placed in all requests */
134    MasterID _dataMasterId;
135
136    /** An intrenal representation of a task identifier within gem5. This is
137     * used so the CPU can add which taskId (which is an internal representation
138     * of the OS process ID) to each request so components in the memory system
139     * can track which process IDs are ultimately interacting with them
140     */
141    uint32_t _taskId;
142
143    /** The current OS process ID that is executing on this processor. This is
144     * used to generate a taskId */
145    uint32_t _pid;
146
147    /** Is the CPU switched out or active? */
148    bool _switchedOut;
149
150    /** Cache the cache line size that we get from the system */
151    const unsigned int _cacheLineSize;
152
153  public:
154
155    /**
156     * Purely virtual method that returns a reference to the data
157     * port. All subclasses must implement this method.
158     *
159     * @return a reference to the data port
160     */
161    virtual Port &getDataPort() = 0;
162
163    /**
164     * Returns a sendFunctional delegate for use with port proxies.
165     */
166    virtual PortProxy::SendFunctionalFunc
167    getSendFunctional()
168    {
169        auto port = dynamic_cast<MasterPort *>(&getDataPort());
170        assert(port);
171        return [port](PacketPtr pkt)->void { port->sendFunctional(pkt); };
172    }
173
174    /**
175     * Purely virtual method that returns a reference to the instruction
176     * port. All subclasses must implement this method.
177     *
178     * @return a reference to the instruction port
179     */
180    virtual Port &getInstPort() = 0;
181
182    /** Reads this CPU's ID. */
183    int cpuId() const { return _cpuId; }
184
185    /** Reads this CPU's Socket ID. */
186    uint32_t socketId() const { return _socketId; }
187
188    /** Reads this CPU's unique data requestor ID */
189    MasterID dataMasterId() const { return _dataMasterId; }
190    /** Reads this CPU's unique instruction requestor ID */
191    MasterID instMasterId() const { return _instMasterId; }
192
193    /**
194     * Get a port on this CPU. All CPUs have a data and
195     * instruction port, and this method uses getDataPort and
196     * getInstPort of the subclasses to resolve the two ports.
197     *
198     * @param if_name the port name
199     * @param idx ignored index
200     *
201     * @return a reference to the port with the given name
202     */
203    Port &getPort(const std::string &if_name,
204                  PortID idx=InvalidPortID) override;
205
206    /** Get cpu task id */
207    uint32_t taskId() const { return _taskId; }
208    /** Set cpu task id */
209    void taskId(uint32_t id) { _taskId = id; }
210
211    uint32_t getPid() const { return _pid; }
212    void setPid(uint32_t pid) { _pid = pid; }
213
214    inline void workItemBegin() { numWorkItemsStarted++; }
215    inline void workItemEnd() { numWorkItemsCompleted++; }
216    // @todo remove me after debugging with legion done
217    Tick instCount() { return instCnt; }
218
219    TheISA::MicrocodeRom microcodeRom;
220
221  protected:
222    std::vector<TheISA::Interrupts*> interrupts;
223
224  public:
225    TheISA::Interrupts *
226    getInterruptController(ThreadID tid)
227    {
228        if (interrupts.empty())
229            return NULL;
230
231        assert(interrupts.size() > tid);
232        return interrupts[tid];
233    }
234
235    virtual void wakeup(ThreadID tid) = 0;
236
237    void
238    postInterrupt(ThreadID tid, int int_num, int index)
239    {
240        interrupts[tid]->post(int_num, index);
241        if (FullSystem)
242            wakeup(tid);
243    }
244
245    void
246    clearInterrupt(ThreadID tid, int int_num, int index)
247    {
248        interrupts[tid]->clear(int_num, index);
249    }
250
251    void
252    clearInterrupts(ThreadID tid)
253    {
254        interrupts[tid]->clearAll();
255    }
256
257    bool
258    checkInterrupts(ThreadContext *tc) const
259    {
260        return FullSystem && interrupts[tc->threadId()]->checkInterrupts(tc);
261    }
262
263    void processProfileEvent();
264    EventFunctionWrapper * profileEvent;
265
266  protected:
267    std::vector<ThreadContext *> threadContexts;
268
269    Trace::InstTracer * tracer;
270
271  public:
272
273
274    /** Invalid or unknown Pid. Possible when operating system is not present
275     *  or has not assigned a pid yet */
276    static const uint32_t invldPid = std::numeric_limits<uint32_t>::max();
277
278    // Mask to align PCs to MachInst sized boundaries
279    static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
280
281    /// Provide access to the tracer pointer
282    Trace::InstTracer * getTracer() { return tracer; }
283
284    /// Notify the CPU that the indicated context is now active.
285    virtual void activateContext(ThreadID thread_num);
286
287    /// Notify the CPU that the indicated context is now suspended.
288    /// Check if possible to enter a lower power state
289    virtual void suspendContext(ThreadID thread_num);
290
291    /// Notify the CPU that the indicated context is now halted.
292    virtual void haltContext(ThreadID thread_num);
293
294   /// Given a Thread Context pointer return the thread num
295   int findContext(ThreadContext *tc);
296
297   /// Given a thread num get tho thread context for it
298   virtual ThreadContext *getContext(int tn) { return threadContexts[tn]; }
299
300   /// Get the number of thread contexts available
301   unsigned numContexts() {
302       return static_cast<unsigned>(threadContexts.size());
303   }
304
305    /// Convert ContextID to threadID
306    ThreadID contextToThread(ContextID cid)
307    { return static_cast<ThreadID>(cid - threadContexts[0]->contextId()); }
308
309  public:
310    typedef BaseCPUParams Params;
311    const Params *params() const
312    { return reinterpret_cast<const Params *>(_params); }
313    BaseCPU(Params *params, bool is_checker = false);
314    virtual ~BaseCPU();
315
316    void init() override;
317    void startup() override;
318    void regStats() override;
319
320    void regProbePoints() override;
321
322    void registerThreadContexts();
323
324    // Functions to deschedule and reschedule the events to enter the
325    // power gating sleep before and after checkpoiting respectively.
326    void deschedulePowerGatingEvent();
327    void schedulePowerGatingEvent();
328
329    /**
330     * Prepare for another CPU to take over execution.
331     *
332     * When this method exits, all internal state should have been
333     * flushed. After the method returns, the simulator calls
334     * takeOverFrom() on the new CPU with this CPU as its parameter.
335     */
336    virtual void switchOut();
337
338    /**
339     * Load the state of a CPU from the previous CPU object, invoked
340     * on all new CPUs that are about to be switched in.
341     *
342     * A CPU model implementing this method is expected to initialize
343     * its state from the old CPU and connect its memory (unless they
344     * are already connected) to the memories connected to the old
345     * CPU.
346     *
347     * @param cpu CPU to initialize read state from.
348     */
349    virtual void takeOverFrom(BaseCPU *cpu);
350
351    /**
352     * Flush all TLBs in the CPU.
353     *
354     * This method is mainly used to flush stale translations when
355     * switching CPUs. It is also exported to the Python world to
356     * allow it to request a TLB flush after draining the CPU to make
357     * it easier to compare traces when debugging
358     * handover/checkpointing.
359     */
360    void flushTLBs();
361
362    /**
363     * Determine if the CPU is switched out.
364     *
365     * @return True if the CPU is switched out, false otherwise.
366     */
367    bool switchedOut() const { return _switchedOut; }
368
369    /**
370     * Verify that the system is in a memory mode supported by the
371     * CPU.
372     *
373     * Implementations are expected to query the system for the
374     * current memory mode and ensure that it is what the CPU model
375     * expects. If the check fails, the implementation should
376     * terminate the simulation using fatal().
377     */
378    virtual void verifyMemoryMode() const { };
379
380    /**
381     *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
382     * This is a constant for the duration of the simulation.
383     */
384    ThreadID numThreads;
385
386    /**
387     * Vector of per-thread instruction-based event queues.  Used for
388     * scheduling events based on number of instructions committed by
389     * a particular thread.
390     */
391    EventQueue **comInstEventQueue;
392
393    /**
394     * Vector of per-thread load-based event queues.  Used for
395     * scheduling events based on number of loads committed by
396     *a particular thread.
397     */
398    EventQueue **comLoadEventQueue;
399
400    System *system;
401
402    /**
403     * Get the cache line size of the system.
404     */
405    inline unsigned int cacheLineSize() const { return _cacheLineSize; }
406
407    /**
408     * Serialize this object to the given output stream.
409     *
410     * @note CPU models should normally overload the serializeThread()
411     * method instead of the serialize() method as this provides a
412     * uniform data format for all CPU models and promotes better code
413     * reuse.
414     *
415     * @param cp The stream to serialize to.
416     */
417    void serialize(CheckpointOut &cp) const override;
418
419    /**
420     * Reconstruct the state of this object from a checkpoint.
421     *
422     * @note CPU models should normally overload the
423     * unserializeThread() method instead of the unserialize() method
424     * as this provides a uniform data format for all CPU models and
425     * promotes better code reuse.
426
427     * @param cp The checkpoint use.
428     */
429    void unserialize(CheckpointIn &cp) override;
430
431    /**
432     * Serialize a single thread.
433     *
434     * @param cp The stream to serialize to.
435     * @param tid ID of the current thread.
436     */
437    virtual void serializeThread(CheckpointOut &cp, ThreadID tid) const {};
438
439    /**
440     * Unserialize one thread.
441     *
442     * @param cp The checkpoint use.
443     * @param tid ID of the current thread.
444     */
445    virtual void unserializeThread(CheckpointIn &cp, ThreadID tid) {};
446
447    virtual Counter totalInsts() const = 0;
448
449    virtual Counter totalOps() const = 0;
450
451    /**
452     * Schedule an event that exits the simulation loops after a
453     * predefined number of instructions.
454     *
455     * This method is usually called from the configuration script to
456     * get an exit event some time in the future. It is typically used
457     * when the script wants to simulate for a specific number of
458     * instructions rather than ticks.
459     *
460     * @param tid Thread monitor.
461     * @param insts Number of instructions into the future.
462     * @param cause Cause to signal in the exit event.
463     */
464    void scheduleInstStop(ThreadID tid, Counter insts, const char *cause);
465
466    /**
467     * Schedule an event that exits the simulation loops after a
468     * predefined number of load operations.
469     *
470     * This method is usually called from the configuration script to
471     * get an exit event some time in the future. It is typically used
472     * when the script wants to simulate for a specific number of
473     * loads rather than ticks.
474     *
475     * @param tid Thread monitor.
476     * @param loads Number of load instructions into the future.
477     * @param cause Cause to signal in the exit event.
478     */
479    void scheduleLoadStop(ThreadID tid, Counter loads, const char *cause);
480
481    /**
482     * Get the number of instructions executed by the specified thread
483     * on this CPU. Used by Python to control simulation.
484     *
485     * @param tid Thread monitor
486     * @return Number of instructions executed
487     */
488    uint64_t getCurrentInstCount(ThreadID tid);
489
490  public:
491    /**
492     * @{
493     * @name PMU Probe points.
494     */
495
496    /**
497     * Helper method to trigger PMU probes for a committed
498     * instruction.
499     *
500     * @param inst Instruction that just committed
501     * @param pc PC of the instruction that just committed
502     */
503    virtual void probeInstCommit(const StaticInstPtr &inst, Addr pc);
504
505   protected:
506    /**
507     * Helper method to instantiate probe points belonging to this
508     * object.
509     *
510     * @param name Name of the probe point.
511     * @return A unique_ptr to the new probe point.
512     */
513    ProbePoints::PMUUPtr pmuProbePoint(const char *name);
514
515    /**
516     * Instruction commit probe point.
517     *
518     * This probe point is triggered whenever one or more instructions
519     * are committed. It is normally triggered once for every
520     * instruction. However, CPU models committing bundles of
521     * instructions may call notify once for the entire bundle.
522     */
523    ProbePoints::PMUUPtr ppRetiredInsts;
524    ProbePoints::PMUUPtr ppRetiredInstsPC;
525
526    /** Retired load instructions */
527    ProbePoints::PMUUPtr ppRetiredLoads;
528    /** Retired store instructions */
529    ProbePoints::PMUUPtr ppRetiredStores;
530
531    /** Retired branches (any type) */
532    ProbePoints::PMUUPtr ppRetiredBranches;
533
534    /** CPU cycle counter even if any thread Context is suspended*/
535    ProbePoints::PMUUPtr ppAllCycles;
536
537    /** CPU cycle counter, only counts if any thread contexts is active **/
538    ProbePoints::PMUUPtr ppActiveCycles;
539
540    /**
541     * ProbePoint that signals transitions of threadContexts sets.
542     * The ProbePoint reports information through it bool parameter.
543     * - If the parameter is true then the last enabled threadContext of the
544     * CPU object was disabled.
545     * - If the parameter is false then a threadContext was enabled, all the
546     * remaining threadContexts are disabled.
547     */
548    ProbePointArg<bool> *ppSleeping;
549    /** @} */
550
551    enum CPUState {
552        CPU_STATE_ON,
553        CPU_STATE_SLEEP,
554        CPU_STATE_WAKEUP
555    };
556
557    Cycles previousCycle;
558    CPUState previousState;
559
560    /** base method keeping track of cycle progression **/
561    inline void updateCycleCounters(CPUState state)
562    {
563        uint32_t delta = curCycle() - previousCycle;
564
565        if (previousState == CPU_STATE_ON) {
566            ppActiveCycles->notify(delta);
567        }
568
569        switch (state)
570        {
571          case CPU_STATE_WAKEUP:
572            ppSleeping->notify(false);
573            break;
574          case CPU_STATE_SLEEP:
575            ppSleeping->notify(true);
576            break;
577          default:
578            break;
579        }
580
581        ppAllCycles->notify(delta);
582
583        previousCycle = curCycle();
584        previousState = state;
585    }
586
587    // Function tracing
588  private:
589    bool functionTracingEnabled;
590    std::ostream *functionTraceStream;
591    Addr currentFunctionStart;
592    Addr currentFunctionEnd;
593    Tick functionEntryTick;
594    void enableFunctionTrace();
595    void traceFunctionsInternal(Addr pc);
596
597  private:
598    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list
599
600  public:
601    void traceFunctions(Addr pc)
602    {
603        if (functionTracingEnabled)
604            traceFunctionsInternal(pc);
605    }
606
607    static int numSimulatedCPUs() { return cpuList.size(); }
608    static Counter numSimulatedInsts()
609    {
610        Counter total = 0;
611
612        int size = cpuList.size();
613        for (int i = 0; i < size; ++i)
614            total += cpuList[i]->totalInsts();
615
616        return total;
617    }
618
619    static Counter numSimulatedOps()
620    {
621        Counter total = 0;
622
623        int size = cpuList.size();
624        for (int i = 0; i < size; ++i)
625            total += cpuList[i]->totalOps();
626
627        return total;
628    }
629
630  public:
631    // Number of CPU cycles simulated
632    Stats::Scalar numCycles;
633    Stats::Scalar numWorkItemsStarted;
634    Stats::Scalar numWorkItemsCompleted;
635
636  private:
637    std::vector<AddressMonitor> addressMonitor;
638
639  public:
640    void armMonitor(ThreadID tid, Addr address);
641    bool mwait(ThreadID tid, PacketPtr pkt);
642    void mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseTLB *dtb);
643    AddressMonitor *getCpuAddrMonitor(ThreadID tid)
644    {
645        assert(tid < numThreads);
646        return &addressMonitor[tid];
647    }
648
649    bool waitForRemoteGDB() const;
650
651    Cycles syscallRetryLatency;
652
653  // Enables CPU to enter power gating on a configurable cycle count
654  protected:
655    void enterPwrGating();
656
657    const Cycles pwrGatingLatency;
658    const bool powerGatingOnIdle;
659    EventFunctionWrapper enterPwrGatingEvent;
660};
661
662#endif // THE_ISA == NULL_ISA
663
664#endif // __CPU_BASE_HH__
665