#include "sim/eventq.hh"
#include "sim/full_system.hh"
#include "sim/insttracer.hh"
+#include "sim/probe/pmu.hh"
#include "sim/system.hh"
+#include "debug/Mwait.hh"
+class BaseCPU;
struct BaseCPUParams;
class CheckerCPU;
class ThreadContext;
+struct AddressMonitor
+{
+ AddressMonitor();
+ bool doMonitor(PacketPtr pkt);
+
+ bool armed;
+ Addr vAddr;
+ Addr pAddr;
+ uint64_t val;
+ bool waiting; // 0=normal, 1=mwaiting
+ bool gotWakeup;
+};
+
class CPUProgressEvent : public Event
{
protected:
{
protected:
- // @todo remove me after debugging with legion done
+ /// Instruction count used for SPARC misc register
+ /// @todo unify this with the counters that cpus individually keep
Tick instCnt;
+
// every cpu has an id, put it in the base cpu
// Set at initialization, only time a cpuId might change is during a
// takeover (which should be done from within the BaseCPU anyway,
* @return a reference to the port with the given name
*/
BaseMasterPort &getMasterPort(const std::string &if_name,
- PortID idx = InvalidPortID);
+ PortID idx = InvalidPortID) override;
/** Get cpu task id */
uint32_t taskId() const { return _taskId; }
TheISA::MicrocodeRom microcodeRom;
protected:
- TheISA::Interrupts *interrupts;
+ std::vector<TheISA::Interrupts*> interrupts;
public:
TheISA::Interrupts *
- getInterruptController()
+ getInterruptController(ThreadID tid)
{
- return interrupts;
+ if (interrupts.empty())
+ return NULL;
+
+ assert(interrupts.size() > tid);
+ return interrupts[tid];
}
- virtual void wakeup() = 0;
+ virtual void wakeup(ThreadID tid) = 0;
void
- postInterrupt(int int_num, int index)
+ postInterrupt(ThreadID tid, int int_num, int index)
{
- interrupts->post(int_num, index);
+ interrupts[tid]->post(int_num, index);
if (FullSystem)
- wakeup();
+ wakeup(tid);
}
void
- clearInterrupt(int int_num, int index)
+ clearInterrupt(ThreadID tid, int int_num, int index)
{
- interrupts->clear(int_num, index);
+ interrupts[tid]->clear(int_num, index);
}
void
- clearInterrupts()
+ clearInterrupts(ThreadID tid)
{
- interrupts->clearAll();
+ interrupts[tid]->clearAll();
}
bool
checkInterrupts(ThreadContext *tc) const
{
- return FullSystem && interrupts->checkInterrupts(tc);
+ return FullSystem && interrupts[tc->threadId()]->checkInterrupts(tc);
}
class ProfileEvent : public Event
public:
+
+ /** Invalid or unknown Pid. Possible when operating system is not present
+ * or has not assigned a pid yet */
+ static const uint32_t invldPid = std::numeric_limits<uint32_t>::max();
+
// Mask to align PCs to MachInst sized boundaries
static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
/// Provide access to the tracer pointer
Trace::InstTracer * getTracer() { return tracer; }
- /// Notify the CPU that the indicated context is now active. The
- /// delay parameter indicates the number of ticks to wait before
- /// executing (typically 0 or 1).
- virtual void activateContext(ThreadID thread_num, Cycles delay) {}
+ /// Notify the CPU that the indicated context is now active.
+ virtual void activateContext(ThreadID thread_num);
/// Notify the CPU that the indicated context is now suspended.
- virtual void suspendContext(ThreadID thread_num) {}
-
- /// Notify the CPU that the indicated context is now deallocated.
- virtual void deallocateContext(ThreadID thread_num) {}
+ /// Check if possible to enter a lower power state
+ virtual void suspendContext(ThreadID thread_num);
/// Notify the CPU that the indicated context is now halted.
virtual void haltContext(ThreadID thread_num) {}
/// Get the number of thread contexts available
unsigned numContexts() { return threadContexts.size(); }
+ /// Convert ContextID to threadID
+ ThreadID contextToThread(ContextID cid)
+ { return static_cast<ThreadID>(cid - threadContexts[0]->contextId()); }
+
public:
typedef BaseCPUParams Params;
const Params *params() const
BaseCPU(Params *params, bool is_checker = false);
virtual ~BaseCPU();
- virtual void init();
- virtual void startup();
- virtual void regStats();
+ void init() override;
+ void startup() override;
+ void regStats() override;
- virtual void activateWhenReady(ThreadID tid) {};
+ void regProbePoints() override;
void registerThreadContexts();
*
* @param os The stream to serialize to.
*/
- virtual void serialize(std::ostream &os);
+ void serialize(CheckpointOut &cp) const override;
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object.
*/
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
+ void unserialize(CheckpointIn &cp) override;
/**
* Serialize a single thread.
* @param os The stream to serialize to.
* @param tid ID of the current thread.
*/
- virtual void serializeThread(std::ostream &os, ThreadID tid) {};
+ virtual void serializeThread(CheckpointOut &cp, ThreadID tid) const {};
/**
* Unserialize one thread.
* @param section The section name of this thread.
* @param tid ID of the current thread.
*/
- virtual void unserializeThread(Checkpoint *cp, const std::string §ion,
- ThreadID tid) {};
+ virtual void unserializeThread(CheckpointIn &cp, ThreadID tid) {};
virtual Counter totalInsts() const = 0;
*/
void scheduleLoadStop(ThreadID tid, Counter loads, const char *cause);
+ /**
+ * Get the number of instructions executed by the specified thread
+ * on this CPU. Used by Python to control simulation.
+ *
+ * @param tid Thread monitor
+ * @return Number of instructions executed
+ */
+ uint64_t getCurrentInstCount(ThreadID tid);
+
+ public:
+ /**
+ * @{
+ * @name PMU Probe points.
+ */
+
+ /**
+ * Helper method to trigger PMU probes for a committed
+ * instruction.
+ *
+ * @param inst Instruction that just committed
+ */
+ virtual void probeInstCommit(const StaticInstPtr &inst);
+
+ /**
+ * Helper method to instantiate probe points belonging to this
+ * object.
+ *
+ * @param name Name of the probe point.
+ * @return A unique_ptr to the new probe point.
+ */
+ ProbePoints::PMUUPtr pmuProbePoint(const char *name);
+
+ /** CPU cycle counter */
+ ProbePoints::PMUUPtr ppCycles;
+
+ /**
+ * Instruction commit probe point.
+ *
+ * This probe point is triggered whenever one or more instructions
+ * are committed. It is normally triggered once for every
+ * instruction. However, CPU models committing bundles of
+ * instructions may call notify once for the entire bundle.
+ */
+ ProbePoints::PMUUPtr ppRetiredInsts;
+
+ /** Retired load instructions */
+ ProbePoints::PMUUPtr ppRetiredLoads;
+ /** Retired store instructions */
+ ProbePoints::PMUUPtr ppRetiredStores;
+
+ /** Retired branches (any type) */
+ ProbePoints::PMUUPtr ppRetiredBranches;
+
+ /** @} */
+
+
+
// Function tracing
private:
bool functionTracingEnabled;
Stats::Scalar numCycles;
Stats::Scalar numWorkItemsStarted;
Stats::Scalar numWorkItemsCompleted;
+
+ private:
+ std::vector<AddressMonitor> addressMonitor;
+
+ public:
+ void armMonitor(ThreadID tid, Addr address);
+ bool mwait(ThreadID tid, PacketPtr pkt);
+ void mwaitAtomic(ThreadID tid, ThreadContext *tc, TheISA::TLB *dtb);
+ AddressMonitor *getCpuAddrMonitor(ThreadID tid)
+ {
+ assert(tid < numThreads);
+ return &addressMonitor[tid];
+ }
+
+ Cycles syscallRetryLatency;
};
#endif // THE_ISA == NULL_ISA