Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / include / simcore.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: simcore.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SIMCORE_H_
#define _SIMCORE_H_
#pragma ident "@(#)simcore.h 1.48 07/02/13 SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* # #
* ## # #### ##### ######
* # # # # # # #
* # # # # # # #####
* # # # # # # #
* # ## # # # #
* # # #### # ######
*
* If you think you need to edit this file you are probably wrong.
* Please talk with Ash to discuss what you want to do before trying
* to hack in here. So hands off !
*/
#include <pthread.h>
typedef struct CONFIG_PROC config_proc_t;
typedef struct CONFIG_DEV config_dev_t;
typedef struct CONFIG_ADDR config_addr_t;
typedef struct PROC_TYPE proc_type_t;
typedef struct DEV_TYPE dev_type_t;
typedef struct DOMAIN domain_t;
typedef struct SERVICE_PROC service_proc_t;
typedef struct SYSTEM system_t;
typedef struct ERROR_CONFIG error_conf_t;
typedef struct REG_MAP reg_map_t;
#include "list.h"
typedef enum MACCESS maccess_t;
/*
* Internal structures for execution data cache simulation
*/
#include "xdcache.h"
/*
* Op fields for memory access operations
*
* Note: These field values are used by the core for embedding
* in decoded instructions. However, processor modules may also
* choose additional specific encodings that are restricted to
* those modules only and are defined elsewhere.
*
* Care should be taken when modifying these codes as not to
* tread on value defined elsewhere (values >= 0x100 && < 0xfff0).
*
* Processor specific modules should use the value
* MA_Non_Gen_Base as the base for their specific definitions.
*
* The generic core values reside in no more than 8 bits
* and are used to define basic load, store and cas operations.
*/
enum MACCESS {
MA_Size_Mask = 0xf,
MA_Size8 = 0x0,
MA_Size16 = 0x1,
MA_Size32 = 0x2,
MA_Size64 = 0x3,
MA_Size128 = 0x4,
MA_Size256 = 0x5,
MA_Size512 = 0x6,
MA_Op_MaskGeneric = 0xf0,
MA_Op_Mask = 0xfff0,
MA_Ld = 0x00,
MA_LdSigned = 0x10,
MA_LdDouble = 0x20, /* SPARC only ? */
MA_LdFloat = 0x30,
MA_St = 0x40,
MA_StFloat = 0x50,
MA_CAS = 0x60,
MA_StDouble = 0x70, /* SPARC only ? */
MA_LdSt = 0x80,
MA_Swap = 0x90,
MA_Non_Gen_Base = 0x100, /* First non generic useable value */
MA_Non_Gen_Skip = 0x10, /* skip value for non-generic codes */
MA_ldu8 = MA_Size8 | MA_Ld,
MA_ldu16 = MA_Size16 | MA_Ld,
MA_ldu32 = MA_Size32 | MA_Ld,
MA_ldu64 = MA_Size64 | MA_Ld,
MA_lddu64 = MA_Size64 | MA_LdDouble, /* loads 64 bit value 64 bit aligned */
MA_stdu64 = MA_Size64 | MA_StDouble,
MA_lddu128 = MA_Size128 | MA_LdDouble, /* loads 2x64 bit
values atomically
128 bit aligned */
MA_lds8 = MA_Size8 | MA_LdSigned,
MA_lds16 = MA_Size16 | MA_LdSigned,
MA_lds32 = MA_Size32 | MA_LdSigned,
MA_lds64 = MA_Size64 | MA_LdSigned,
MA_st8 = MA_Size8 | MA_St,
MA_st16 = MA_Size16 | MA_St,
MA_st32 = MA_Size32 | MA_St,
MA_st64 = MA_Size64 | MA_St,
MA_ldfp8 = MA_Size8 | MA_LdFloat,
MA_ldfp16 = MA_Size16 | MA_LdFloat,
MA_ldfp32 = MA_Size32 | MA_LdFloat,
MA_ldfp64 = MA_Size64 | MA_LdFloat,
#ifdef PROCESSOR_SUPPORTS_QUADFP
MA_ldfp128 = MA_Size128 | MA_LdFloat,
#endif
MA_stfp8 = MA_Size8 | MA_StFloat,
MA_stfp16 = MA_Size16 | MA_StFloat,
MA_stfp32 = MA_Size32 | MA_StFloat,
MA_stfp64 = MA_Size64 | MA_StFloat,
#ifdef PROCESSOR_SUPPORTS_QUADFP
MA_stfp128 = MA_Size128 | MA_StFloat,
#endif
MA_cas32 = MA_Size32 | MA_CAS,
MA_cas64 = MA_Size64 | MA_CAS,
/* Are these generic ? FIXME */
MA_ldstub = MA_Size8 | MA_LdSt,
MA_swap = MA_Size32 | MA_Swap
};
/*
* These macros must be passed an op masked with MA_Op_Mask.
* It is intended that they be included as part of a architecture
* specific form, hence the underscore prefix.
*/
#define _IS_MA_LOAD(_op) \
(MA_Ld == (_op) || MA_LdSigned == (_op) || \
MA_LdDouble == (_op) || MA_LdFloat == (_op) || \
MA_LdSt == (_op) || MA_CAS == (_op) || MA_Swap == (_op))
#define _IS_MA_STORE(_op) \
(MA_St == (_op) || MA_StDouble == (_op) || \
MA_StFloat == (_op) || \
MA_LdSt == (_op) || MA_CAS == (_op) || MA_Swap == (_op))
#define _IS_MA_ATOMIC(_op) \
(MA_LdSt == (_op) || MA_CAS == (_op) || MA_Swap == (_op))
/*
* Data structures passed as pointers, but private to the
* simulator core.
*/
typedef void *(*instn_exec_t)();
typedef struct XICACHE_INSTN xicache_instn_t;
typedef struct XICACHE_LINE xicache_line_t;
typedef struct XICACHE xicache_t;
typedef union DECODED_INSTN decoded_instn_t;
typedef struct BP_INFO bp_info_t;
typedef struct BREAKPOINT breakpoint_t;
/* Sigh : used as a hack for breakpoints -
* try and remove this - FIXME */
typedef LIST_DEF( simcpu_list_t, simcpu_t );
extern simcpu_list_t simcpu_list;
/*
* Simulator core CPU structure ..
* defines NINT integer registers, NFP floating point
* registers etc ...
*/
#define NINT 32
#define NFP_128 16
#define NFP_64 32
#define NFP_32 64
typedef struct ERROR {
void * itep; /* track itlb entry with error until demapped */
void * dtep; /* track dtlb entry with error until demapped */
uint8_t tlb_idx[4]; /* tlb entry with parity error */
#define IMDU_IDX 0
#define IMTU_IDX 1
#define DMDU_IDX 2
#define DMTU_IDX 3
uint64_t l2_write; /* write to l2 on partial store or atomic hit */
uint64_t partial_st; /* partial store l2 access */
uint8_t reg; /* register number with ECC error */
tvaddr_t addr; /* pa or va in error */
bool_t check_xicache; /* check error conditions on xdcache access */
bool_t check_dtlb; /* check error conditions on dtlb access */
bool_t check_xdcache; /* check error conditions on xdcache access */
error_conf_t * errlistp; /* errors to post for this simcpu */
} error_t;
#define STATE_DISABLED 0x1LL
#define STATE_PARKED 0x2LL
#define RUNNABLE(_sp) ((_sp)->state_bits == 0)
#define DISABLED(_sp) (((_sp)->state_bits & STATE_DISABLED) != 0)
#define SET_DISABLED(_sp) ((_sp)->state_bits |= STATE_DISABLED)
#define CLR_DISABLED(_sp) ((_sp)->state_bits &= ~STATE_DISABLED)
#define PARKED(_sp) (((_sp)->state_bits & STATE_PARKED) != 0)
#define SET_PARKED(_sp) ((_sp)->state_bits |= STATE_PARKED)
#define CLR_PARKED(_sp) ((_sp)->state_bits &= ~STATE_PARKED)
#if ERROR_TRAP_GEN /* { */
/*
* Error Trap Gen Stuff
*/
typedef enum {
ERROR_ON_LOAD,
ERROR_ON_STORE,
ERROR_ON_LOAD_OR_STORE
} ee_access_t;
typedef enum {
EE_PARSED, /* user input has been completely parsed */
EE_ASSIGNED, /* assigned to an sp (watching for trigger) */
EE_TRIGGERED /* error event trigger conditions met */
} ee_status_t;
#define ERROR_TL_NONE 0xffffffff
#define ERROR_INSTN_CNT_NONE UINT64_MAX
typedef union {
uint64_t all; /* used to test/clear all options */
struct {
uint64_t opts_pad:53;
uint64_t trigger_cnt:1;
uint64_t tl:1;
uint64_t priv:1;
uint64_t access:1;
uint64_t address:1;
uint64_t pc:1;
uint64_t instn_cnt:1;
uint64_t target_cpuid:1;
uint64_t error_str:1;
uint64_t trap_num:1;
uint64_t sp_intr:1;
} bits;
} error_event_options_t;
typedef struct error_event {
uint64_t trap_num;
int sp_intr;
char *error_str;
int64_t target_cpuid;
int64_t instn_cnt;
int64_t pc;
struct {
ee_access_t access;
uint64_t addr;
} address;
int priv;
int tl;
ee_status_t ee_status;
int trigger_cnt;
error_event_options_t options;
struct error_asi *temp_error_asi_list_rootp;
struct error_event *nextp;
} error_event_t;
typedef struct error_asi {
int asi;
uint64_t va; /* 0x1 means all VAs */
uint64_t nand_mask; /* applied to register before or_mask */
uint64_t or_mask;
uint32_t access_cnt;
uint64_t asi_reg;
uint32_t id; /* unique id for each error_asi */
uint64_t cpu_mask; /* bitmap of valid cpus for this error_asi */
struct error_asi *nextp;
} error_asi_t;
#endif /* ERROR_TRAP_GEN } */
#if HOST_CPU_LITTLE_ENDIAN
#define FP_32_INDX(_i) ((_i) ^ 1)
#else
#define FP_32_INDX(_i) (_i)
#endif
struct SIMCPU {
uint64_t intreg[NINT]; /* Register file info always first elements ! */
union {
ieee_fp32_t s32[NFP_32];
ieee_fp64_t s64[NFP_64];
#ifdef PROCESSOR_SUPPORTS_QUADFP
ieee_fp128_t s128[NFP_128]; /* largest FP type to ensure correct alignment */
#endif
} fpreg;
tvaddr_t pc; /* Program counter */
tvaddr_t npc; /* Next PC if used by target */
uint64_t miscreg[8]; /* misc 64 bit registers - target dependent usage */
/* for target=sparcv9: */
/* misc[0] = CCR */
uint64_t scratch64; /* emergency scratch */
/*
* Different reasons why we should be paying attention
*
* To optimize the 'any attention asserted' check, we
* use a union to map the different reasons to bytes
* within one 64-bit word that be tested with one read.
*/
volatile union {
uint64_t _attention; /* true if some simulator exception to consider */
struct {
uint8_t _exec_loop_reset;
uint8_t _sync_pending;
uint8_t _async_event; /* set if another entity changed simcpu_t state */
uint8_t _exception_pending;
uint8_t _xdcache_trans_flush_pending;
uint8_t _xicache_trans_flush_pending;
uint8_t _xicache_instn_flush_pending;
} _subatt;
} _att;
#define attention _att._attention
#define exec_loop_reset _att._subatt._exec_loop_reset
#define sync_pending _att._subatt._sync_pending
#define async_event _att._subatt._async_event
#define exception_pending _att._subatt._exception_pending
#define xdcache_trans_flush_pending _att._subatt._xdcache_trans_flush_pending
#define xicache_trans_flush_pending _att._subatt._xicache_trans_flush_pending
#define xicache_instn_flush_pending _att._subatt._xicache_instn_flush_pending
/*
* The error caught by this ASSERT is if more uint8_t's are added to _subatt
* such that it becomes larger that _attention - which would break the
* combined attention check.
*/
#define ATTENTION_SANITY_CHECK do { \
ASSERT(sizeof (((simcpu_t *)NULL)->_att) == sizeof (((simcpu_t *)NULL)->attention)); \
} while (0)
volatile uint64_t state_bits; /* collection of state bits */
exec_thread_t * etp; /* pointer to exec_thread that this scheduler list is on */
simcpu_t * headp; /* pointer to the head simcpu of the scheduler list */
simcpu_t * nextp; /* next in scheduler list */
xicache_t * xicachep; /* pointer to local execution cache */
/* cpu specific handler for an xicache miss */
void (*xic_miss)(simcpu_t *, xicache_line_t *, tvaddr_t addr);
config_addr_t * xic_miss_addrp; /* cpu specific cache of address used to */
/* satisfy last XC miss - only used by sp->xic_miss */
int gid; /* global simcpu id */
/* How this simulator cpu corresponds to the
* specific CPU defined.
*/
config_proc_t * config_procp;
void * specificp; /* target specific data pointer */
void (*decodemep)(simcpu_t *, xicache_instn_t *); /* decodeme function for this cpu */
simcycle_t cycle;
simcycle_t cycle_target;
void (*cycle_target_match)(simcpu_t * sp);
simcycle_t cycle_quantum_start;
simcycle_t total_instr;
#if ERROR_INJECTION
error_t * errorp; /* pointer to flags and stashed error values */
bool_t error_enabled; /* cycle match happened and errors to post */
bool_t error_check; /* first-level flag to check error conditions */
uint8_t error_priv; /* privilege level to post error */
#endif
#if ERROR_TRAP_GEN /* { */
simcycle_t error_cycle;
bool_t error_pending;
bool_t error_cycle_reached;
error_event_t *eep;
#endif /* ERROR_TRAP_GEN } */
#if PERFORMANCE_CHECK /* { */
/* FIXME: Hack - to go away */
#define PERF_CYCLE_GAP 10000000 /* figure time for every 1M instructions */
hrtime_t last_hrtime;
hrtime_t total_hrtime;
simcycle_t perf_target;
uint64_t prev_icount;
uint64_t xdc_hits, xdc_misses, xdc_flushes;
uint64_t prev_xdc_hits, prev_xdc_misses, prev_xdc_flushes;
uint64_t xic_hits, xic_misses, xic_flushes;
uint64_t prev_xic_hits, prev_xic_misses, prev_xic_flushes;
#endif /* } */
/*
* Misc stuff to (potentially go away) FIXME
*/
#if ENABLE_MAGIC_TRAPS /* { */
/* This for the magic trap that enables us to count instructions */
simcycle_t magic_count;
#endif /* } */
/*
* additional cache structures
*/
bp_info_t * bp_infop;
uint32_t tagstate;
void *debug;
/*
* xdcache is large - keep at the end to optimize structure
* offsets.
*/
xdcache_t xdc;
};
/*
* DBGELMIN will execute when DBG_EL_MIN or DBG_EL are set in debug_bits.
* DBGEL will only execute if DBG_EL is set in debug_bits.
*/
#ifndef NDEBUG
#define DBG_EL 0x2LL
#define DBG_EL_MIN 0x4LL
#define DBG_ILLINST 0x10LL
#define DBG_DECODE 0x40000000LL
#define DBG_EXEC_LOOP 0x100000000LL
#define DBG_XCACHE 0x20000000000LL
#define DBGEL(s) do { if (debug_bits & (DBG_EL)) { s } } while (0)
#define DBGELMIN(s) do { if (debug_bits & (DBG_EL_MIN|DBG_EL)) { s } } while (0)
#define DBGILLINST(s) do { if (debug_bits & (DBG_ILLINST)) { s } } while (0)
#define DBGDECODE(s) do { if (debug_bits & DBG_DECODE) { s } } while (0) /* debug exec_loop */
#define DBGEXECLOOP(s) do { if (debug_bits & DBG_EXEC_LOOP) { s } } while (0) /* debug exec_loop */
#define DBGXCACHE(s) do { if (debug_bits & DBG_XCACHE) { s } } while (0) /* debug x[di]cache */
#else
#define DBGEL(s) do { } while (0)
#define DBGELMIN(s) do { } while (0)
#define DBGILLINST(s) do { } while (0)
#define DBGDECODE(s) do { } while (0)
#define DBGEXECLOOP(s) do { } while (0) /* debug exec_loop */
#define DBGXCACHE(s) do { } while (0) /* debug x[di]cache */
#endif
#define DFT_EXEC_QUANTUM 8192
#define EXEC_QUANTUM (options.quantum)
#define set_sync_pending(_sp) do { (_sp)->sync_pending = true; } while (0)
extern simcpu_t * sim_cpu_alloc(
config_proc_t * cfp,
void * specificp);
typedef struct {
bool_t mode; /* true if SP defined in config file */
volatile bool_t poweron; /* true if SP has signalled a poweron */
} sp_info_t;
struct SIMSTATUS {
volatile bool_t running; /* start/stop execution */
volatile bool_t initialized; /* true when legion init complete */
sp_info_t sp; /* service proc info */
};
extern void init_simstatus(void);
extern void simcore_start(void);
extern void simcore_stop(void);
extern void simcore_cpu_enable(simcpu_t *sp);
extern void simcore_cpu_disable(simcpu_t *sp);
extern void simcore_cpu_state_park(simcpu_t *sp);
extern void simcore_cpu_state_unpark(simcpu_t *sp);
struct EXEC_THREAD {
uint_t id; /* Id for the exec_thread */
simcpu_t * allp; /* pointer to all cpus assigned */
uint_t nsimcpus; /* number of simcpus assigned to this thread */
};
extern void exec_loop(exec_thread_t *);
extern void exec_loop_dh(exec_thread_t *);
/* Get the number of instructions executed by simcpu_t */
/* Avoids incrementing both cycle and total_instr in the loop */
#define ICOUNT(_sp) ((_sp)->total_instr + \
((_sp)->cycle -(_sp)->cycle_quantum_start))
extern void cycle_target_off(simcpu_t *sp);
#if !defined(NDEBUG) /* { */
void simcore_update_debug_bits(uint64_t newval);
#endif /* } */
#define _XCACHE_TAGSTATE_SHIFT 6
#define XCACHE_TAGSTATE_MASK (7 << _XCACHE_TAGSTATE_SHIFT)
#define XCACHE_TAGSTATE_PHYS (0 << _XCACHE_TAGSTATE_SHIFT)
#define XCACHE_TAGSTATE_TLN (1 << _XCACHE_TAGSTATE_SHIFT)
#define XCACHE_TAGSTATE_TL0 (2 << _XCACHE_TAGSTATE_SHIFT)
#define XCACHE_TAGSTATE_TLN_U (3 << _XCACHE_TAGSTATE_SHIFT)
#define XCACHE_TAGSTATE_TL0_U (4 << _XCACHE_TAGSTATE_SHIFT)
extern void xcache_set_tagstate(simcpu_t * sp);
#ifdef __cplusplus
}
#endif
#endif /* _SIMCORE_H_ */