readfb.c 6.33 KB
/*==============================================================================
    $Revision: 1.1.1.2 $
    $Date: 2002/10/29 08:07:15 $
    $Author: blythe $
    $Source: /root/leakn64/depot/rf/sw/bbplayer/tools/gcord/cord/readfb.c,v $
==============================================================================*/
#include <stdio.h>

#include "global.h"
#include "proc.h"

/*------------------------------------------------------------------------------
	place procedures by
		A only
		A and B, in A order
		B only
	the result is stored in mapB.
	returns the # of procedures in the new map.
------------------------------------------------------------------------------*/
#define MARK_A	  1
#define MARK_B    2
#define MARK_A_B  3

static int merge_reorder_file(
	Proc_map *mapA, int n_A, 
	Proc_map *mapB, int n_B)
{
	int 	i;
	int 	n_max = (n_A > n_B)? n_A: n_B;
	int 	tmp_index = 0;
	static  Proc_map       *tmp_map = NULL;
	
	if (tmp_map == NULL)
	    tmp_map = alloc_proc_map();

	clear_proc_flag(); /* clear the flag */
	for (i= 0; i< n_A; i++){
	    if (mapA[i].freq != 0)
	    	mapA[i].proc->emitted = MARK_A;
	}
	for (i= 0; i< n_B; i++){
	    if (mapB[i].freq != 0)
	    	mapB[i].proc->emitted |= MARK_B;
	}

		/* find A only */
	for (i= 0; i< n_A; i++){
	    if (mapA[i].proc->emitted == MARK_A )
		tmp_map[tmp_index++] = mapA[i];
	}
		/* find A intersect B in A order */
	for (i= 0; i< n_A; i++){
	    if (mapA[i].proc->emitted == MARK_A_B){
		tmp_map[tmp_index].proc = mapA[i].proc;
		tmp_map[tmp_index++].freq = mapA[i].proc->freq;
		/* proc->freq has the merged freq */
	    }
	}
		/* find B only */
	for (i= 0; i< n_B; i++){
	    if (mapB[i].proc->emitted == MARK_B)
		tmp_map[tmp_index++] = mapB[i];
	}

		/* find A with merged freq 0 */
	for (i= 0; i< n_A; i++){
	    if (mapA[i].proc->freq ==0)
		tmp_map[tmp_index++] = mapA[i];
	}

		/* find B only with freq 0 */
	for (i= 0; i< n_B; i++){
	    if (mapB[i].proc->emitted == MARK_B && 
		mapB[i].proc->freq ==0)
		tmp_map[tmp_index++] = mapB[i];
	}


	if (tmp_index != n_max)
	    error("internal");
	memcpy(mapB, tmp_map, n_max*sizeof(Proc_map));

	return n_max;
}

/*------------------------------------------------------------------------------
  read the reorder file
------------------------------------------------------------------------------*/
int read_reorder_file(char *file, Proc_map *proc_map)
{
	Proc	*proc;
	FILE 	*fd;		/* reorder file */
	char	line[512];	/* input line from reorder file */
	unsigned	magic = 0;
	unsigned	version = 0;
	int		start = 0;
	int		n_proc = 0;
	
	/*------------------
	  open file
	------------------*/
	fd = fopen(file, "r");
	if (fd == NULL){
		error("cannot read reorder file %s", 
			file);
	}

	clear_proc_flag(); /* clear the flag */

	/*------------------
	  get lines 
	------------------*/
	while (fgets(line, sizeof(line), fd) != NULL && !start) {
	    if  (strlen(line) >= sizeof(line) - 1 && 
			line[sizeof(line)-2] != '\n'){
            	error("reorder file line too long, shouldn't exceed %d", 
			sizeof(line) - 1);
	    }
	    if(line[0] == '#'){ 	/* comments */
	    }else if (line[0] == '$'){ 	/* directives */
		char	directive[100];	/* directive name */
		sscanf(line, "%s", directive);
		if (!strcmp(directive, "$timestamp")){
		    sscanf(line, "%*s %x", &bin.timestamp);
		}else if (!strcmp(directive, "$version")){
		    sscanf(line, "%*s %d", &version);
		}else if (!strcmp(directive, "$magic")){
		    sscanf(line, "%*s %d", &magic);
		}else if (!strcmp(directive, "$start")){
		    start = 1;	/* start of procedure list */
		}else if (!strcmp(directive, "$name")){ /* name of binary */
		    char name[128];
		    char *basename, *base_in_file;
		    sscanf(line, "%*s %s", name);
		    basename = strrchr(name, '/');
		    basename = basename ? basename +1 : name;
		    base_in_file = strrchr(option.in_file, '/');
		    base_in_file = base_in_file ? base_in_file +1 : option.in_file;
		    if (strcmp(basename, base_in_file))
			warning("feedback file %s derived from %s !!!",
			    file, name);
		}
	    }else{ 			/* reordering list */
		if (!magic){
		    error("%s is not a feedback file", file);
		}else{
		    error("syntax error in feedback file %s\n%s", file, line);
		}
	    }
	}

	if (! (version == 1 || version == 2))
	    error("invalid version");
	/*------------------
	  read procedures
	------------------*/
	while (fgets(line, sizeof(line), fd) != NULL) {
	    if(line[0] == '#'){ 	/* comments */
		continue;
	    }else if (line[0] == '$'){ 	/* directives */
		error("%s: directive after $start",file);
	    }else{ 			/* reordering list */
		char		proc_name[256];	/* procedure name */
		char		file_name[256];	/* file name */
		Uint32	begin;
		Uint32	size;
		Uint32	freq;
		Proc	*proc;

		if (version == 1){
		    sscanf(line, "%s %s %x %x %llu", 
			proc_name,
			file_name,
			&begin,
			&size,
			&freq);
		}else{	/* version 2 */
		    sscanf(line, "%s %s %llu", 
			proc_name,
			file_name,
			&freq);
		}
		proc = find_proc_by_name(proc_name, file_name);
		if(option.debug)
			printf("proc_name %s file_name %s porc 0x%x \n", 
				proc_name, file_name, proc);
			
		if (proc){
		    proc->emitted = TRUE;
		    proc->freq += freq; 
		    proc_map[n_proc].freq = freq;
		    proc_map[n_proc++].proc = proc;
	    	}
	    }
	}
	return n_proc;
}

/*------------------------------------------------------------------------------
   read one or multiple reorder files
------------------------------------------------------------------------------*/
void read_reorder_files(void){
	int i;
	int n_files;
	Proc_map	*proc_map;
	Proc_map	*tmp_map;
	int		n_proc;
	int		n_tmp_proc;

	tmp_map = alloc_proc_map();
	proc_map = alloc_proc_map();

	/* find the number of files */
	for (n_files = 0; option.reorder_file[n_files] != NULL; n_files++);

	/* read last file */
	n_proc = read_reorder_file(option.reorder_file[n_files-1], proc_map);

	if (n_files > 1){
	    for (i = n_files-2; i >=0 ; i--){
	        n_tmp_proc = 
			read_reorder_file(option.reorder_file[i], tmp_map);
		n_proc = merge_reorder_file( tmp_map, n_tmp_proc,
			proc_map, n_proc);
	    }
	}

	for (i = 0; i< n_proc; i++){
	    attach_proc_list(proc_map[i].proc);
	    proc_map[i].proc->emitted = TRUE;
	}

	attach_proc_with_no_feedback();
	if (status.proc_not_match == TRUE && option.verbose == TRUE){
	    note("Feedback file(s) may be out of date. You may want to regenerate the\n      feedback file(s) for better performance. Use cord -v for more info.");
	}
}