#include "cubes.h" /**************************************************************************** NAME star_product PURPOSE This function generates the biggest cube that can be created from two adjacent cubes. The variable for which adjacency is checked is predefined as the current_var. SYNOPSIS int star_product(cube1,cube2,result_cube) long int *cube1,*cube2,*result_cube; DESCRIPTION The two cubes are used to form the biggest possible cube out of them. If they are not adjacent for the current_var or if their output are disjoint, no cube can be formed and the value 0 is returned. Otherwise 1 is returned. COORDINATES McGill University Electrical Engineering VLSI Lab MONTREAL CANADA 19 june 1984 AUTHOR Michel DAGENAIS ************************************************************************/ int star_product(cube1,cube2,result_cube) long int *cube1,*cube2,*result_cube; { long int result, /* word containing the intersection */ *end_input, /* pointer to the word after the last word of input */ *end_output, /* pointer to the word after the last word of cube */ *merged_word, /* pointer to the word in which is the current var */ intersect_mask; /* mask that contains 10 for intersecting var and 00 */ /* for non-intersecting var */ int common_output; merged_word = cube1 + current_word_index; end_input = cube1 + input_length; end_output = cube1 + total_length; #ifdef DEBUG printf("cube1 %lx merged_word %lx current_mask11 %lx current_mask10 %lx\n", cube1,merged_word,current_mask11,current_mask10); #endif for(; cube1 < end_input ; cube1++) /* we put the intersection in result_word */ { result = *cube1 & *cube2; /* we check if the intersection is null on one variable */ intersect_mask = ((result << 1) | result) & mask10; if(intersect_mask != mask10) /* the null intersection should be only on the current_var which means that the two cubes are adjacent along that variable. If the null part is for another variable, 0 is returned and no merging is possible along that variable. If the merging can be performed, that part becomes an x. */ { if((intersect_mask | current_mask10) != mask10)return(0); if(cube1 != merged_word) return(0); result |= current_mask11; } *result_cube = result; cube2++; result_cube++; } /* the input of the new cube is formed, we must now check if its output is empty, and if not compute it */ common_output = 0; for(; cube1 < end_output ; cube1++) { *result_cube = *cube1 & *cube2; if(*result_cube != 0L) common_output = 1; cube2++; result_cube++; } if(common_output) return(1); else return(0); } /**************************************************************************** NAME covers, covers_input, absorb, covers_list PURPOSE This function tells you if a cube covers completely another one. SYNOPSIS int covers(cube1,cube2) long int *cube1,*cube2; int covers_input(cube1,cube2) long int *cube1, *cube2; int absorb(cube1,cube2) long int *cube1,*cube2; int covers_list(cube,list) long int *cube; struct cube_list *list; DESCRIPTION -covers returns 1 if cube1 covers cube2 and 0 otherwise. -covers_input returns 1 if the input of cube1 covers the input of cube2. -absorb returns -1 if nobody covers nobody, 0 if cube1 and cube2 are equal, 1 if cube1 covers cube2 and 2 if cube2 covers cube1. -covers_list returns 1 if cube covers all the cube in the list and 0 otherwise. COORDINATES McGill University Electrical Engineering VLSI Lab MONTREAL CANADA 19 june 1984 AUTHOR Michel DAGENAIS ************************************************************************/ int covers(cube1,cube2) long int *cube1,*cube2; { long int *end_of_cube; /* pointer to the word after the last of cube*/ end_of_cube = cube1 + total_length; for(; cube1 < end_of_cube ; cube1++) { if((*cube1 & *cube2) != *cube2 ) return(0); cube2++; } return(1); } /**********************************************************************/ #ifdef DEBUG int covers_input(cube1,cube2) long int *cube1,*cube2; { long int *end_of_input; /* pointer to the word after the last of cube*/ end_of_input = cube1 + input_length; for(; cube1 < end_of_input ; cube1++) { if((*cube1 & *cube2) != *cube2 ) return(0); cube2++; } return(1); } #endif /***********************************************************************/ int absorb(cube1,cube2) long int *cube1,*cube2; { long int *end_of_cube, /* pointer to the word after the last of cube */ and_cubes; /* intersection of the two cubes */ int cube1_covers, /* logic variable tells if 1 covers 2 up to now */ cube2_covers; /* logic variable tells if 2 covers 1 up to now */ end_of_cube = cube1 + total_length; cube1_covers = 1; cube2_covers = 1; for(; cube1 < end_of_cube ; cube1++) { and_cubes = *cube1 & *cube2; if(and_cubes != *cube1) { if(cube1_covers == 0) return(-1); else cube2_covers = 0; } if(and_cubes != *cube2) { if(cube2_covers == 0) return(-1); else cube1_covers = 0; } cube2++; } if(cube1_covers) { if(cube2_covers) return(0); /* both cubes are equal */ else return(1); /* cube 1 covers cube 2 */ } else return(2); /* cube 2 covers cube 1 */ } /********************************************************************/ int covers_list(cube,list) long int *cube; struct cube_list *list; { for(; list != NULL ; list = list->next_cube) { if(covers(cube,list->cube) == 0) return(0); } return(1); } /**************************************************************************** NAME intersect, intersect_list PURPOSE These functions check if two cubes do intersect. SYNOPSIS int intersect(cube1,cube2) long int *cube1,*cube2; int intersect_list(cube,list) struct cube_list *list; long int *cube; DESCRIPTION -intersect returns 1 if cube1 and cube2 do intersect and 0 otherwise. -intersect_list returns 1 if cube1 intersects with any cube in list and 0 otherwise. COORDINATES McGill University Electrical Engineering VLSI Lab MONTREAL CANADA 19 june 1984 AUTHOR Michel DAGENAIS ************************************************************************/ int intersect(cube1,cube2) long int *cube1,*cube2; { long int *end_of_input, /* pointer to word after input of cube */ *end_of_output, /* pointer to word after output of cube */ result; /* intersection of the cubes */ end_of_input = cube1 + input_length; end_of_output = cube1 + total_length; for(; cube1 < end_of_input ; cube1++) { result = *cube1 & *cube2; /* we want to detect if the intersection is null for any variable */ if((((result << 1) | result ) & mask10) != mask10) return(0); cube2++; } for(; cube1 < end_of_output ; cube1++) { if((*cube1 & *cube2) != 0L) return(1); cube2++; } return(0); } /*************************************************************************/ int intersect_list(cube,list) long int *cube; struct cube_list *list; { for(; list != NULL ; list = list->next_cube) { if(intersect(cube,list->cube)) return(1); } return(0); } /**************************************************************************** NAME disjoint_sharp PURPOSE This function takes a list of disjoint cubes and sharp from it another cube. The list is updated to contain the result. SYNOPSIS int disjoint_sharp(list,cube) long int *cube; struct cube_list **list; DESCRIPTION the function takes each cube in the list, see if the other cube intersect with it. If so a new list is computed such that it is disjoint from the cube but the union of the cube and the new list has the same coverage as with the old list and the cube. It is the disjoint sharp operation as defined by Hong and Opstako for their MINI program. The implementation is different however. The function returns 1 when the list is empty after the sharp. Otherwise the function returns 0. COORDINATES McGill University Electrical Engineering VLSI Lab MONTREAL CANADA 19 june 1984 AUTHOR Michel DAGENAIS ************************************************************************/ int disjoint_sharp(list,cube) long int *cube; struct cube_list **list; { struct cube_list *present_cube_list, /*pointer to the cube_list element considered*/ **previous_cube, /*pointer to the next_cube element of previous*/ /* cube, useful when we want to delete an */ /* element in the list */ *temp_pointer; /* temporary pointer when a cube is splitted */ long int *end_input, /* pointer to end of input of a cube */ *end_output, /* pointer to end of output of a cube */ *present_cube, /* pointer to the cube considered */ *sharping_cube, /* pointer to the cube we sharp from the list*/ result, /* contains the intersection of two cubes */ mask_var; /* mask one variable in a long int */ previous_cube = list; end_input = cube + input_length; end_output = cube + total_length; for(; (present_cube_list = *previous_cube) != NULL ;) { present_cube = present_cube_list->cube; /* If the two cubes do not intersect we simply go to the next cube in the list since there is nothing to sharp here. */ if(intersect(cube,present_cube) == 0) { previous_cube = &(present_cube_list->next_cube); continue; } for(sharping_cube = cube ; sharping_cube < end_input ; sharping_cube++) /* we compute the intersection of the two cubes and see for which variables it is smaller than the cube from which we want to remove the intersection */ { result = (*sharping_cube & *present_cube) ^ *present_cube; if(result != NULL) /* the intersection does not cover all the cube we will have to split it for all the variables for which we have X in the cube in the list and not X for the sharping cube */ { for(mask_var = 3 ; mask_var != NULL ; mask_var = mask_var << 2) { if(result & mask_var) /* We split the cube in two by allocating a new cube and giving the value 1 to a cube and 0 to the other for the input variable of the cube which was x. One cube will be disjoint from the sharping cube and skipped in the list while the other will intersect and is smaller such that by repetitive splitting, we will end with a cube completely covered by the sharping cube; for this last cube the output common with the sharping cube will be reset to 0 as a result of the sharp operation. */ { temp_pointer = present_cube_list->next_cube; present_cube_list->next_cube = copy_and_alloc_cube_list(present_cube_list->cube); *present_cube = ~(mask_var & *sharping_cube) & *present_cube; present_cube = (present_cube - present_cube_list->cube) + (present_cube_list->next_cube)->cube; previous_cube = &(present_cube_list->next_cube); present_cube_list = present_cube_list->next_cube; present_cube_list->next_cube = temp_pointer; *present_cube = ((~mask_var) | *sharping_cube) & *present_cube; } } } present_cube++; } /* If all the output bits are reset to 0 as result of the sharp operation, the last cube becomes empty and is removed from the list. After we go to process the next cube in the list */ result = NULL; for(; sharping_cube < end_output;) { *present_cube = *present_cube & (~ *sharping_cube); if(*present_cube) result = 1; sharping_cube++; present_cube++; } if(result == NULL) { temp_pointer = present_cube_list->next_cube; free_cube_list(present_cube_list); present_cube_list = temp_pointer; *previous_cube = temp_pointer; } else { previous_cube = &(present_cube_list->next_cube); } } if(*list == NULL) return(1); return(0); } b