* ========== 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.
#pragma ident "@(#)simcore.h 1.48 07/02/13 SMI"
* 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 !
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
;
typedef enum MACCESS maccess_t
;
* Internal structures for execution data cache simulation
* 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.
MA_Op_MaskGeneric
= 0xf0,
MA_LdDouble
= 0x20, /* SPARC only ? */
MA_StDouble
= 0x70, /* SPARC only ? */
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
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
,
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
,
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_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
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
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 */
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 */
#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 /* { */
EE_PARSED
, /* user input has been completely parsed */
EE_ASSIGNED
, /* assigned to an sp (watching for trigger) */
EE_TRIGGERED
/* error event trigger conditions met */
#define ERROR_TL_NONE 0xffffffff
#define ERROR_INSTN_CNT_NONE UINT64_MAX
uint64_t all
; /* used to test/clear all options */
typedef struct error_event
{
error_event_options_t options
;
struct error_asi
*temp_error_asi_list_rootp
;
struct error_event
*nextp
;
typedef struct error_asi
{
uint64_t va
; /* 0x1 means all VAs */
uint64_t nand_mask
; /* applied to register before or_mask */
uint32_t id
; /* unique id for each error_asi */
uint64_t cpu_mask
; /* bitmap of valid cpus for this error_asi */
#endif /* ERROR_TRAP_GEN } */
#if HOST_CPU_LITTLE_ENDIAN
#define FP_32_INDX(_i) ((_i) ^ 1)
#define FP_32_INDX(_i) (_i)
uint64_t intreg
[NINT
]; /* Register file info always first elements ! */
#ifdef PROCESSOR_SUPPORTS_QUADFP
ieee_fp128_t s128
[NFP_128
]; /* largest FP type to ensure correct alignment */
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: */
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.
uint64_t _attention
; /* true if some simulator exception to consider */
uint8_t _exec_loop_reset
;
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
;
#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)); \
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
config_proc_t
* config_procp
;
void * specificp
; /* target specific data pointer */
void (*decodemep
)(simcpu_t
*, xicache_instn_t
*); /* decodeme function for this cpu */
void (*cycle_target_match
)(simcpu_t
* sp
);
simcycle_t cycle_quantum_start
;
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 */
#if ERROR_TRAP_GEN /* { */
bool_t error_cycle_reached
;
#endif /* ERROR_TRAP_GEN } */
#if PERFORMANCE_CHECK /* { */
/* FIXME: Hack - to go away */
#define PERF_CYCLE_GAP 10000000 /* figure time for every 1M instructions */
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
;
* Misc stuff to (potentially go away) FIXME
#if ENABLE_MAGIC_TRAPS /* { */
/* This for the magic trap that enables us to count instructions */
* additional cache structures
* xdcache is large - keep at the end to optimize structure
* 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.
#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 */
#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 */
#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(
bool_t mode
; /* true if SP defined in config file */
volatile bool_t poweron
; /* true if SP has signalled a poweron */
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
);
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
);
#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
);