#ifndef VALVE_TAIL_DIAG_H #define VALVE_TAIL_DIAG_H #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #endif #include "local_probe.h" #include #include #include #include #ifndef KD_TRACE #define KD_TRACE 1 #endif typedef struct {unsigned mxcsr;unsigned short cw,sw;int err;} KdEnv; typedef struct {uint64_t key[5];double cm,vel;KdEnv env;int ready;} KdMemo; typedef struct {uint64_t jac;int group,hit;uint64_t key[5];double cm,vel;KdEnv before,after;uint64_t tail,lookup,capture;int executed,pad;} KdRecord; extern int kd_scope; extern uint64_t kd_jac; extern KdMemo kd_memo; static inline uint64_t kd_clock(void){unsigned lo,hi;__asm__ __volatile__("lfence\n\trdtsc\n\tlfence":"=a"(lo),"=d"(hi)::"memory");return ((uint64_t)hi<<32)|lo;} static inline KdEnv kd_env(void){KdEnv e;__asm__ __volatile__("stmxcsr %0;fnstcw %1;fnstsw %2":"=m"(e.mxcsr),"=m"(e.cw),"=m"(e.sw)::"memory");e.err=errno;return e;} static inline int kd_env_equal(KdEnv a,KdEnv b){return a.mxcsr==b.mxcsr && a.cw==b.cw && a.sw==b.sw && a.err==b.err;} static inline int kd_finite(const uint64_t *key){for(int i=0;i<5;i++)if((key[i]&UINT64_C(0x7ff0000000000000))==UINT64_C(0x7ff0000000000000))return 0;return 1;} /* Diagnostic-only lookup: its answer NEVER bypasses the original tail. * Only a baseline entry is considered. Probe misses never populate the slot. */ static inline int kd_lookup(const uint64_t *key,KdEnv e,double *cm,double *vel){ if(!kd_memo.ready || !kd_env_equal(e,kd_memo.env) || memcmp(key,kd_memo.key,40))return 0; *cm=kd_memo.cm;*vel=kd_memo.vel;return 1; } void kd_start(void);void kd_finish(void);void kd_new_jac(void); void kd_before(KdRecord*,double,double,double,double,double); void kd_after(KdRecord*,double,double,uint64_t,int); void kd_matrix(double,const double*,const double*); void kd_eval_exit(double,const double*,const double*,const double*,int,NativePropertyCache*,NativePipeCache*,ModelJacobianWorkspace*); #endif