📄 docpu.h
字号:
#define A1_OUT(s) L1_OUT(s)
// The A1_OUT macro outputs the s string and execution time of the program fragment
// labeled by the val checkpoint in relation to the exeution time of the fragment labeled
// by the base checkpoint.
#define Ax_OUT(s,base,val) Lx_OUT(s, Ax_GET(base), Ax_GET(val))
// The A_LIST_ITER prints all results for measurement of the
// t checkpoint
#define A_LIST_ITER(t) printf("LIST_ITER {\n"); \
for(DoCPU_tmp=0;DoCPU_tmp<A_NITER;DoCPU_tmp++) \
printf("\t%d\n",DoCPU_buff[t][DoCPU_tmp]); \
printf("} LIST_ITER\n");
// The A_LIST_ITER_AS_TABLE prints all measurment results for the
// program fragment labeled by the t checkpoint and generates
// a table suitable for importing into MS Graph
#define A_LIST_ITER_AS_TABLE(s,buf) \
printf(s); \
for(DoCPU_tmp=0;DoCPU_tmp<A_NITER;DoCPU_tmp++) \
printf("\t%d",buf[DoCPU_tmp]); \
printf("\n");
/*
// #define Lx_OUTx(s,buf_base,buf_val,x_factor)\
// printf("%s : %d%%\n",s,100*(cycle_mid(DoCPU_buff[buf_val],0)/x_factor)/
// (cycle_mid(DoCPU_buff[buf_base],0)/x_factor));
// #define Lx_OUT_DEBUG(s,buf_base,buf_val) printf("%s : %d%%, %d%%\n",s,cycle_mid(DoCPU_buff[buf_val],0),cycle_mid(DoCPU_buff[buf_base],0));
*/
// MACROS FOR DISPLAYING THE PROGRESS
// ======================================
// Macro displaying the rotating "propeller"
#define VVV if (DoCPU_vcp >= strlen(DoCPU_v)) DoCPU_vcp = 0; \
sprintf(DoCPU_s,"\rDoCPU:%c\r",DoCPU_v[DoCPU_vcp]); \
PRINT(DoCPU_s); DoCPU_vcp++;
// Macro displaying the current progress in percents
#define PRINT_PROGRESS(x) sprintf(DoCPU_s,"\rProgress : %3d%%\r",(x)); \
PRINT(DoCPU_s);
// FUNCTION FOR DISPLAYING DIAGRAMS "ON THE fLY"
// ---------------------------------------------
// ARG:
// size - size of the diagram bar
//
// n_sym - number of characters within the string (NULL == 80)
//
// max - maximum value of size.
// == 0 : max is equal to the doubled value of the first size
// == -1 : resetting the previous value of form_factor and returning
//
// nl - == 0 : proportional scale
// == 1 : logarithmic scale
void online_graph(int size, int n_sym, int max, int nl)
{
int a;
int form_factor;
static graph_size = 0;
// resetting graph_size to zero
if (max == -1) { graph_size = 0; return; }
// calculating graph_size by the first size value
if ((!max) && (!graph_size)) graph_size = size * 2;
// calculating the diagram length
if (!n_sym) n_sym = MAX_GRAPH_LEN;
// calculating the form_factor
if (!max) form_factor = graph_size / n_sym;
else
form_factor = max / n_sym;
// special processing for logarithmic string
if (nl)
{
size = 10*log(size);
form_factor=1;
}
if (!form_factor) form_factor = 1;
size /= form_factor;
// displaying the diagram
for (a = 0; a < size; a++)
{
if (a >= (n_sym-3))
{ // diagram limits are exceeded
if (size > (n_sym-3)*3) printf(">");
if (size > (n_sym-3)*2) printf(">");
if (size > (n_sym-3)*1) printf(">");
break;
}
printf(GRAPH_CHAR);
}
printf("\n");
}
// Macro for quick call to online_graph with default arguments
#define GRAPH(a) online_graph(a,0,0,0);
// Macros for initializing online_graph
#define RE_GRAPH online_graph(0,0,-1,0);
/*----------------------------------------------------------------------------
*
* INPUT
*
----------------------------------------------------------------------------*/
// reading memory area. Is it needed?
#define A_READ(p, size_p) for(DoCPU_tmp=0; DoCPU_tmp < size_p; DoCPU_tmp += sizeof(int))\
DoCPU_tmp1+=((int *)(p+DoCPU_tmp))[0];
/*----------------------------------------------------------------------------
FUNCTIONS FOR WORKING WITH MEMORY AND CACHE
----------------------------------------------------------------------------*/
// The _malloc32 macro allocates x bytes of memory and guarantees that the allocated block
// will start from the address that is a multiple of 32
#define _malloc32(x) (( (((int) malloc((x)+0x20)) + 0x20) & 0xFFFFFFE0 ));
// The _align32 macro aligns the p pointer by address that is a multiple of 32 bytes
#define _align32(p) (( (((int) (p)) + 0x20) & 0xFFFFFFE0 ));
// The CLEAR_L2_CACHE macro fill L2 cache with garbage, thus
// flushing the data that was written into it earlier.
int CLEAR_L2_CACHE()
{
int a;
int x = 0;
if (!p_cache) p_cache = (int *) malloc(_NORMAL);
for (a = 0; a<_NORMAL; a++)
x += *(int *)((int)p_cache+a);
return x;
}
int CLEAR_ALL()
{
// !!!UNDER CONSTRUCTION!!!
return 0;
}
// This macro flushes store buffers on P-III
void _DoCPU_a_fflush()
{
#ifdef __FLUSH__
_DoCPU_a_flush();
#endif
}
#define RM for(DoCPU_tmp = 0; DoCPU_tmp < 10; DoCPU_tmp++) DoCPU_float_tmp+=0.99;
/*----------------------------------------------------------------------------
SERVICE FUNCTIONS
----------------------------------------------------------------------------*/
// * FUNC: int getargv(char *arg_name, char *arg_val)
// * Function for checking if the argument keys are present and received
//
// If the arg_name argument is specified in the command line,
// the function returns non-negative value;
//
// If the arg_name argument is missing from the command line
// (or, if its length exceeds MAX_STR_LEN), the function returns -1;
//
// If the argument has a key, separated from it by a colon
// (something like "/XXX:666"), its string value is returned in arg_val
// provided that arg_val is not equal to zero;
//
// If arg_val==NULL this means that the argument's key is not needed;
//
// If the key is present, the function also attempts to return its numeric
// value (received from atol);
//
// NOTE: If the function returns 0, the situation is ambiguous: either
// the argument has no key at all, or the key is not a numeric value, or the key
// is actually equal to zero. If this is the case, check the contents of
// arg_val to clarify the situation
int getargv(char *arg_name, char *arg_val)
{
int a;
int* p;
unsigned int c;
char buf_arg[MAX_STR_LEN];
char buf_val[MAX_STR_LEN];
#ifndef __argv
char** __argv;
int __argc=0;
#endif
if (!arg_name) return -1;
if (arg_val) arg_val[0] = 0; // Initialization
// Testing all arguments
for (a = 1; a < __argc; a++)
{
if (strlen(__argv[a]) >= MAX_STR_LEN) return -1;
// Parsing the argument syntax and copying its name into buf_arg
for (c=0;c!=(1+strlen(__argv[a]));c++)
{
if (__argv[a][c] == ':') { buf_arg[c] = 0; break; }
buf_arg[c] = __argv[a][c];
}
// Copying the key (if there is any) into buf_val
if (__argv[a][c] == ':') strcpy(buf_val, &__argv[a][c +1]); else buf_val[0] = 0;
// If this is the argument that is needed, then copy its value into arg_val
if (!strcmp(arg_name,buf_arg))
{
if (arg_val) strcpy(arg_val,buf_val);
return atol(buf_val);
}
}
return -1;
}
// The IFHELP macro displays the s string provided that the "/?"
// command-line option is specified, and terminates the program execution
#define IFHELP(s) if (getargv("/?",0)!=-1){ PRINT(_TEXT(s)); return 0; }
// The GETARGV is the "wrapper" for the getargv function.
// If the s key is present in the command line, it stores the key value into the
// val variable. If the s key is not present in the command line, the val variable
// does not change.
#define GETARGV(s,val) DoCPU_tmp=getargv(s,NULL); \
if (DoCPU_tmp!=-1) val=DoCPU_tmp;
//#define A_FLUSH _DoCPU_a_flush();
//#define A_FFLUSH _DoCPU_a_fflush();
//#define A_WAIT Sleep(TIME_TO_WAIT);
/*----------------------------------------------------------------------------
*
* PROFILER KERNEL FUNCTIONS
*
----------------------------------------------------------------------------*/
int* A0(void* x)
{
Sleep(100);
return DoCPU(x);
}
/*----------------------------------------------------------------------------
*
* SERVICE FUNCTIONS OF THE PROFILER KERNEL
*
----------------------------------------------------------------------------*/
// This function returns the clock frequency of the processor in MHz
int GetCPUclock(void)
{
#define to_time 1
int tmp;
unsigned int t;
volatile time_t timer;
tmp = getargv("$Fcpu",0);
if (tmp <= 0)
{
if (!(tmp=CPU_CLOCK))
{
timer = time(NULL);
while(timer == time(NULL));
timer = time(NULL);
A1(&t);
while( timer+to_time > time(NULL));
t=A2(&t);
tmp=((double)t) / ((double)1000000) / ((double)to_time);
CPU_CLOCK=tmp;
}
}
if (getargv("$DEBUG.print.Fcpu",0)!=-1) printf(">DEBUG:Fcpu=%d\n",tmp);
return tmp;
}
// This function converts clocks into seconds
float cpu2timeu(unsigned int ticks, int tt)
{
if (tt)
return ((float )ticks)/CLOCKS_PER_SEC;
if (!CPU_CLOCK) CPU_CLOCK=GetCPUclock();
return ((float )ticks)/CPU_CLOCK/1000000;
}
#ifdef _NORDTSC
float cpu2time(int ticks)
{
return cpu2timeu(ticks, 0);
}
#else
float cpu2time(int ticks)
{
return cpu2timeu(ticks, 1);
}
#endif
/*----------------------------------------------------------------------------
*
* KERNEL FUNCTIONS FOR PROCESSING THE RESULTS
*
----------------------------------------------------------------------------*/
int cycle_min(int *buff, int n_buff)
{
int a, tmp;
if (!n_buff) n_buff = DoCPU_BUFF_SIZE;
tmp = buff[0];
for(a = 0; a < n_buff; a++)
if (buff[a] < tmp) tmp = buff[a];
return tmp;
}
int cycle_max(int *buff, int n_buff)
{
int a, tmp;
if (!n_buff) n_buff = DoCPU_BUFF_SIZE;
tmp = buff[0];
for(a = 0; a < n_buff; a++)
if (buff[a] > tmp) tmp = buff[a];
return tmp;
}
int _compare(unsigned int *arg1, unsigned int *arg2 )
{
if (*arg2 >= *arg1) return -1;
// else
return +1;
}
unsigned int cycle_mid(unsigned int *buff, int nbuff)
{
int a, xa = 0;
if (!nbuff) nbuff = A_NITER;
// 锐觌
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -