text: #ifndef CORE_H
  #define CORE_H
  
  // some forward declarations for cross includes
  class Thread;
  class Network;
  class MemoryManagerBase;
  class MemoryManagerFast;
  class PerformanceModel;
  class ClockSkewMinimizationClient;
  class ShmemPerfModel;
  class TopologyInfo;
  class CheetahManager;
  
  #include "mem_component.h"
  #include "fixed_types.h"
  #include "lock.h"
  #include "packet_type.h"
  #include "subsecond_time.h"
  #include "bbv_count.h"
  #include "cpuid.h"
  #include "hit_where.h"
  
  struct MemoryResult {
     HitWhere::where_t hit_where;
     subsecond_time_t latency;
  };
  
  MemoryResult makeMemoryResult(HitWhere::where_t _hit_where, SubsecondTime _latency);
  void applicationMemCopy(void *dest, const void *src, size_t n);
  
  class Core
  {
     public:
  
        enum State
        {
           RUNNING = 0,
           INITIALIZING,
           STALLED,
           SLEEPING,
           WAKING_UP,
           IDLE,
           BROKEN,
           NUM_STATES
        };
  
        enum lock_signal_t
        {
           INVALID_LOCK_SIGNAL = 0,
           MIN_LOCK_SIGNAL,
           NONE = MIN_LOCK_SIGNAL,
           LOCK,
           UNLOCK,
           MAX_LOCK_SIGNAL = UNLOCK,
           NUM_LOCK_SIGNAL_TYPES = MAX_LOCK_SIGNAL - MIN_LOCK_SIGNAL + 1
        };
  
        enum mem_op_t
        {
           INVALID_MEM_OP = 0,
           MIN_MEM_OP,
           READ = MIN_MEM_OP,
           READ_EX,
           WRITE,
           MAX_MEM_OP = WRITE,
           NUM_MEM_OP_TYPES = MAX_MEM_OP - MIN_MEM_OP + 1
        };
  
        /* To what extend to make a memory access visible to the simulated instruction */
        enum MemModeled
        {
           MEM_MODELED_NONE,      /* Not at all (pure backdoor access) */
           MEM_MODELED_COUNT,     /* Count in #accesses/#misses */
           MEM_MODELED_COUNT_TLBTIME, /* Count in #accesses/#misses, queue TLBMissInstruction on TLB miss */
           MEM_MODELED_TIME,      /* Count + account for access latency (using MemAccessInstruction) */
           MEM_MODELED_FENCED,    /* Count + account for access latency as memory fence (using MemAccessInstruction) */
           MEM_MODELED_RETURN,    /* Count + time + return data to construct DynamicInstruction */
        };
  
        static const char * CoreStateString(State state);
  
        Core(SInt32 id);
        ~Core();
  
        // Query and update branch predictor, return true on mispredict
        bool accessBranchPredictor(IntPtr eip, bool taken, IntPtr target);
  
        MemoryResult readInstructionMemory(IntPtr address,
              UInt32 instruction_size);
  
        MemoryResult accessMemory(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr d_addr, char* data_buffer, UInt32 data_size, MemModeled modeled = MEM_MODELED_NONE, IntPtr eip = 0, SubsecondTime now = SubsecondTime::MaxTime(), bool is_fault_mask = false);
        MemoryResult nativeMemOp(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr d_addr, char* data_buffer, UInt32 data_size);
  
        void accessMemoryFast(bool icache, mem_op_t mem_op_type, IntPtr address);
  
        void logMemoryHit(bool icache, mem_op_t mem_op_type, IntPtr address, MemModeled modeled = MEM_MODELED_NONE, IntPtr eip = 0);
        bool countInstructions(IntPtr address, UInt32 count);
  
        void emulateCpuid(UInt32 eax, UInt32 ecx, cpuid_result_t &res) const;
  
        // network accessor since network is private
        int getId() const { return m_core_id; }
        Thread *getThread() const { return m_thread; }
        void setThread(Thread *thread) { m_thread = thread; }
        Network *getNetwork() { return m_network; }
        PerformanceModel *getPerformanceModel() { return m_performance_model; }
        ClockSkewMinimizationClient* getClockSkewMinimizationClient() const { return m_clock_skew_minimization_client; }
        MemoryManagerBase *getMemoryManager() { return m_memory_manager; }
        const MemoryManagerBase *getMemoryManager() const { return m_memory_manager; }
        ShmemPerfModel* getShmemPerfModel() { return m_shmem_perf_model; }
        const ComponentPeriod* getDvfsDomain() const { return m_dvfs_domain; }
        TopologyInfo* getTopologyInfo() { return m_topology_info; }
        const TopologyInfo* getTopologyInfo() const { return m_topology_info; }
        const CheetahManager* getCheetahManager() const { return m_cheetah_manager; }
  
        State getState() const { return m_core_state; }
        void setState(State core_state) { m_core_state = core_state; }
        UInt64 getInstructionCount() { return m_instructions; }
        BbvCount *getBbvCount() { return &m_bbv; }
        UInt64 getInstructionsCallback() { return m_instructions_callback; }
        bool isEnabledInstructionsCallback() { return m_instructions_callback != UINT64_MAX; }
        void setInstructionsCallback(UInt64 instructions) { m_instructions_callback = m_instructions + instructions; }
        void disableInstructionsCallback() { m_instructions_callback = UINT64_MAX; }
  
        void enablePerformanceModels();
        void disablePerformanceModels();
  
        void updateSpinCount(UInt64 instructions, SubsecondTime elapsed_time)
        {
           m_spin_loops++;
           m_spin_instructions += instructions;
           m_spin_elapsed_time += elapsed_time;
        }
  
     private:
        core_id_t m_core_id;
        const ComponentPeriod* m_dvfs_domain;
        MemoryManagerBase *m_memory_manager;
        Thread *m_thread;
        Network *m_network;
        PerformanceModel *m_performance_model;
        ClockSkewMinimizationClient *m_clock_skew_minimization_client;
        Lock m_mem_lock;
        ShmemPerfModel* m_shmem_perf_model;
        BbvCount m_bbv;
        TopologyInfo *m_topology_info;
        CheetahManager *m_cheetah_manager;
  
        State m_core_state;
  
        static Lock m_global_core_lock;
  
        MemoryResult initiateMemoryAccess(
              MemComponent::component_t mem_component,
              lock_signal_t lock_signal,
              mem_op_t mem_op_type,
              IntPtr address,
              Byte* data_buf, UInt32 data_size,
              MemModeled modeled,
              IntPtr eip,
              SubsecondTime now);
  
        void hookPeriodicInsCheck();
        void hookPeriodicInsCall();
  
        IntPtr m_icache_last_block;
  
        UInt64 m_spin_loops;
        UInt64 m_spin_instructions;
        SubsecondTime m_spin_elapsed_time;
  
     protected:
        // Optimized version of countInstruction has direct access to m_instructions and m_instructions_callback
        friend class InstructionModeling;
  
        // In contrast to core->m_performance_model->m_instructions, this one always increments,
        // also when performance modeling is disabled or when instrumenation mode is CACHE_ONLY or FAST_FORWARD
        UInt64 m_instructions;
        UInt64 m_instructions_callback;
        // HOOK_PERIODIC_INS implementation
        UInt64 m_instructions_hpi_callback;
        UInt64 m_instructions_hpi_last;
        static UInt64 g_instructions_hpi_global;
        static UInt64 g_instructions_hpi_global_callback;
  };
  
  #endif
  