#ifndef _fastsim_h #define _fastsim_h /****************************************************************************** ** FILE: fastsim.h -- Part of the FastSim simulation system. ** Interface to the fastsim runtime system. */ #include <sys/types.h> #include <libelf.h> #include <math.h> #include <assert.h> void xmain(); /* Main function defined in Facile */ /****************************************************************************** * Value of simulator command line options. */ extern int verbose; extern int debug_level; extern char* execfile; extern char* logfile; /****************************************************************************** * External functions called by FastSim that can be overridden. * Default versions of these functions are provided in libfs.a. */ void xexit(); /* called on simulator exit */ void xno_instruction(); /* may be called by Facile ?exec attribute */ void xno_default(); /* may be called by Facile switch statements */ /****************************************************************************** * External functions called by FastSim that cannot be overridden. */ /* Interface to detect SIGSEGV and SIGBUS signals */ extern void* xmem_test_address; /* address to test */ extern unsigned char xmem_test_flag; /* set to true surrounding test */ extern unsigned char xmem_test_failed; /* result of test; true if failed */ unsigned char xmem_load8_test(void *va); unsigned short xmem_load16_test(void *va); unsigned long xmem_load32_test(void *va); unsigned long long xmem_load64_test(void *va); /* There should probably be some corresponding store tests */ /* write message to a log file */ void xlog(int lvl, const char*, ...); /* dump simulator statistics to the logfile */ extern size_t nstat; void xstats(); /****************************************************************************** * Other definitions used in the Facile/C interface. */ #define TARGET_VADDR_MASK 0x80000000 /* Or'ed with all target addresses to generate translated target addr */ /* Types used by generated simulators */ typedef char* string_t; typedef unsigned char cc_t; typedef unsigned long token_stream_t; typedef struct queue { unsigned char size; /* max # of elements in allocated array */ unsigned char length; /* # of elemets in use (ie, queue length) */ unsigned char begin; /* index of first element in the queue */ unsigned char end; /* just past the last element in the queue */ void *data; /* dynamically allocated array */ } queue_t; /* Allocate a new queue data array to fix queue after assignment */ void queue_realloc(queue_t*, unsigned long width); /* Reallocate a queue data array when more space is needed */ void queue_grow(queue_t*, unsigned long width); /* Global variables defined by the simulation framework */ extern Elf *elf; extern caddr_t break_value; /* Interface functions to query & manipulate simulation data */ token_stream_t start_pc(); unsigned long start_sp(); static inline token_stream_t token_stream(unsigned long addr) { return addr; } static inline unsigned char stream_lt(token_stream_t s1, token_stream_t s2) { return s1 < s2; } static inline unsigned char stream_le(token_stream_t s1, token_stream_t s2) { return s1 <= s2; } static inline unsigned char stream_eq(token_stream_t s1, token_stream_t s2) { return s1 == s2; } static inline unsigned char stream_ne(token_stream_t s1, token_stream_t s2) { return s1 != s2; } static inline unsigned char stream_ge(token_stream_t s1, token_stream_t s2) { return s1 >= s2; } static inline unsigned char stream_gt(token_stream_t s1, token_stream_t s2) { return s1 > s2; } static inline token_stream_t stream_add(token_stream_t stream, unsigned long delta) { return stream + delta; } static inline token_stream_t stream_sub(token_stream_t stream, unsigned long delta) { return stream - delta; } unsigned long stream_bits32(token_stream_t, unsigned long offset, unsigned long width, unsigned long lo, unsigned long hi); unsigned long long stream_bits64(token_stream_t, unsigned long offset, unsigned long width, unsigned long lo, unsigned long hi); unsigned long sign_extend32(unsigned long src, unsigned long width); unsigned long long sign_extend64(unsigned long long src, unsigned long width); union Cast32 { float f; signed long s; unsigned long u; }; extern union Cast32 cast32; union Cast64 { double f; signed long long s; unsigned long long u; }; extern union Cast64 cast64; /* floating point sqrt */ float fsqrt32(float); double fsqrt64(double); /* operators on signed/unsigned long values that set condition codes */ ulong_t uadd32_cc(cc_t*, ulong_t, ulong_t); long sadd32_cc(cc_t*, long, long); ulong_t usub32_cc(cc_t*, ulong_t, ulong_t); long ssub32_cc(cc_t*, long, long); ulong_t uand32_cc(cc_t*, ulong_t, ulong_t); ulong_t uor32_cc(cc_t*, ulong_t, ulong_t); ulong_t uxor32_cc(cc_t*, ulong_t, ulong_t); /* operators on signed/unsigned long long values that set condition codes */ u_longlong_t uadd64_cc(cc_t*, u_longlong_t, u_longlong_t); longlong_t sadd64_cc(cc_t*, longlong_t, longlong_t); u_longlong_t usub64_cc(cc_t*, u_longlong_t, u_longlong_t); longlong_t ssub64_cc(cc_t*, longlong_t, longlong_t); u_longlong_t uand64_cc(cc_t*, u_longlong_t, u_longlong_t); u_longlong_t uor64_cc(cc_t*, u_longlong_t, u_longlong_t); u_longlong_t uxor64_cc(cc_t*, u_longlong_t, u_longlong_t); /* floating point operators that set condition codes */ float fsub32_cc(cc_t*, float, float); double fsub64_cc(cc_t*, double, double); extern void* dummybuf; /****************************************************************************** * Types, variables, and functions to support fast-forwarding. * * The primary function is fast_forward(), which looks up the given RTS data * in the memoization cache and tries to switch to the fast-forwarded version * of the simulator. Upon return, the RTS data in the "init" variable will be * set to the correct value for whatever point the simulation has reached and * slow simulation can be (re)started. */ typedef struct { size_t bytes; long buf[0x100]; } pack_data_t; typedef struct { size_t bytes; void* buf; } packed_queue_t; /* RTS data should be packed into pack_data before calling * either fast_forward() or write_result(). */ extern pack_data_t pack_data; /* make sure last word of pack_data.buf han no random data */ static inline size_t fill_pack_data() { size_t words, align; words = (pack_data.bytes+3) / 4; assert(words < 0x100); align = pack_data.bytes & 0x3; if(align) pack_data.buf[words-1] &= 0xffffffff << (8*(4 - align)); return words*4; } /* Try to switch to fast-forwarded simulation */ void fast_forward(); /* Insure static versions of global vars have the same structure as their * dynamic versions. Called at start of recovery from memoization miss. */ void ff_copy_to_stat(); /* * The following structures are used to store * control data in the memoization cache */ #define INDEX_ACTION 0 #define DLL32_ACTION 0x7fff #define DLL64_ACTION 0x7ffe #define RESULT1_ACTION -1 #define RESULT8_ACTION -2 #define RESULTN_ACTION -3 typedef struct Action { ushort_t action; /* >=0 for actions; <0 for results */ ushort_t bytes; /* bytes to previous action or result */ } action_t; typedef struct Result8 { char action; /* -1 for 1 bit results; otherwise -2 */ uchar_t result; /* up to 8 bits of result data */ ushort_t bytes; /* bytes to previous action or result */ void *next; } result_8_t; typedef struct ResultN { char action; /* should always be -3 */ uchar_t words; /* # of words of result data */ ushort_t bytes; /* bytes to previous action or result */ struct ResultN *next; } result_N_t; #define ACTION_BYTES(act) (((action_t*)(act))->bytes & 0xfffc) #define ACTION_FLAGS(act) (((action_t*)(act))->bytes & 0x0003) #define IS_RESULT(xx) (*((signed char*)(xx)) < 0) /* Fast-forwarded version of main (generated by fs) */ void ff_main(action_t*); /* * Flags providing info about or control of the fast-forwarding process */ /* True if a fast-forwarding simulator was generated */ extern int ff_memoize; /* True if transitioning back to slow-sim */ extern int ff_recover; /* * Functions called by automatically generated code */ /* Allocate unitialized bytes in the memoization cache */ void *ff_alloc(size_t); /* Allocate and initialize a new action structure */ void ff_write_action(ushort_t); /* Allocate and initialize a record to verify the RTS data in pack_data */ void ff_write_result_N(); /* Returns a pointer to packed data written by ff_write_result_N */ void *ff_recover_result_N(); /* Allocate and initialize a record to verify up to 8 bits of data */ uchar_t ff_write_result_8(uchar_t); /* Allocate and initialize a record to verify 1 bit of data */ int ff_write_result_1(int); /* Miss processing */ void ff_miss_result_N(result_N_t*,size_t); void ff_miss_result_8(result_8_t*,uchar_t); void ff_miss_result_1(result_8_t*,int); /* Search the linked list of possible successors * to find the given result identifier. */ static inline void* ff_find_result_N(void *data) { result_N_t *rr, *rr0 = (result_N_t*)data; size_t bytes = fill_pack_data(); size_t words = bytes / 4; #ifdef STATS extern u_longlong_t count_resultN_fast; ++count_resultN_fast; #endif for(rr=rr0; rr; rr=(result_N_t*)rr->next) { long* data = (long*)(rr+1); assert(rr->action == RESULTN_ACTION); if(rr->words == words && !memcmp(data,pack_data.buf,bytes)) return data + words; } ff_miss_result_N(rr0,bytes); /* longjmp return */ assert(!"Should not be here!"); return NULL; } /* Search the linked list of possible successors * to find the given result identifier. */ static inline void* ff_find_result_8(void *data, uchar_t result) { result_8_t *rr, *rr0 = (result_8_t*)data; #ifdef STATS extern u_longlong_t count_result8_fast; ++count_result8_fast; #endif for(rr=rr0; rr; rr=(result_8_t*)rr->next) { assert(rr->action == RESULT8_ACTION); if(rr->result == result) return rr+1; } ff_miss_result_8(rr0,result); /* longjmp return */ assert(!"Should not be here!"); return NULL; } /* Same as above, but optimized for the case where there * are only 2 possible results (ie, IF or WHILE). */ static inline void* ff_find_result_1(void *data, int result) { result_8_t *rr0 = (result_8_t*)data; #ifdef STATS extern u_longlong_t count_result1_fast; ++count_result1_fast; #endif assert(rr0->action == RESULT1_ACTION); if((int)rr0->result == result) return rr0+1; if(rr0->next) return rr0->next; ff_miss_result_1(rr0,result); /* jongjmp return */ assert(!"Should not be here!"); return NULL; } /* Process the INDEX action */ void* ff_index_action(action_t*); /* Process the DLL action */ void* ff_dll_action(action_t*); #ifdef STATS extern u_longlong_t count_action_fast; #define COUNT_ACTIONS ++count_action_fast; #else #define COUNT_ACTIONS #endif #endif