#include "cubes.h" /**************************************************************************** NAME retain_check_node, unretain_inferior_check_node DESCRIPTION Once we arrived to a decision concerning the scanned_node, we can have it executed it by the proper function in the list above. SYNOPSIS retain_check_node() unretain_inferior_check_node() DESCRIPTION The scanned node is removed from the undecided list and put in the proper list. Also its status is set properly. These functions are similar to the normal retain and unretain functions except that they are much slower because they do an extensive verification of the validity of the decision taken. This function should only be used to verify the rest of the program during the extensive validation pass of the program. COORDINATES McGill University Electrical Engineering MONTREAL CANADA 17 july 1984 AUTHOR Michel DAGENAIS ***********************************************************************/ retain_check_node() { struct node **temp_in_vector; free_list_of_cubes(&scanned_cube); temp_in_vector = prime_nodes; scanned_cube = copy_and_alloc_cube_list(scanned_node->cube); for(; temp_in_vector < unretain_nodes; temp_in_vector++) { if(((*temp_in_vector)->status & DECIDED) && (((*temp_in_vector)->status & RETAINED) == NULL)) continue; if((*temp_in_vector) == scanned_node) continue; if(disjoint_sharp(&scanned_cube,(*temp_in_vector)->cube)) { foutput_cube_and_links(stderr,scanned_node); foutput_graph_vector(stderr,retained_nodes,unretain_nodes,); fatal_program_error("no way you will retain this node"); } } send_user_message("a node is retained ok"); free_list_of_cubes(&scanned_cube); free_list_of_cubes(&(scanned_node->uncovered)); scanned_node->status = DECIDED_RETAINED; current_node = scanned_node; increment_pass_count(); scan_affected_retained_ancestors(); current_node = scanned_node; scan_affected_retained_descendants(); } /***************************************************************************/ unretain_inferior_check_node() { struct node **temp, *temp_node; struct cube_list *temp_cube; temp_cube = copy_and_alloc_cube_list(scanned_node->cube); temp = prime_nodes; for(; temp < unretain_nodes ; temp++) { temp_node = *temp; if((temp_node->status & RETAINED) == NULL) continue; if(disjoint_sharp(&temp_cube,temp_node->cube)) { foutput_cube_and_links(stderr,scanned_node); fatal_program_error("an inferior cube is in fact covered"); } } temp = retained_nodes; for(; temp < unretain_nodes ; temp++) { temp_node = *temp; if(temp_node->status & DECIDED) continue; if(temp_node == scanned_node) continue; if(covers_list(temp_node->cube,temp_cube)) { free_list_of_cubes(&temp_cube); send_user_message("a node is unretained inferior ok"); break; } } if(temp_cube != NULL) { foutput_cube_and_links(stderr,scanned_node); fatal_program_error("a node is unretained inferior but should not"); } scanned_node->status = DECIDED_INFERIOR; current_node = scanned_node; increment_pass_count(); scan_affected_unretain_ancestors(); current_node = scanned_node; scan_affected_unretain_descendants(); } /********************************************************************** NAME check_cycle PURPOSE When we are in the software validation process this function can check that we really have a cycle. SYNOPSIS check_cycle() DESCRIPTION Each node in the cycle is checked to see if it is covered or essential in which case it is not a real cycle. COORDINATES McGill Electrical Engineering VLSI lab MONTREAL CANADA 17 august 1984 AUTHOR Michel DAGENAIS ************************************************************************/ check_cycle() { struct node **temp1, **temp2; struct cube_list *temp_cube; temp1 = retained_nodes; for(; temp1 < unretain_nodes ; temp1++) { if(((*temp1)->status & DECIDED) == NULL) { temp2 = prime_nodes; temp_cube = copy_and_alloc_cube_list((*temp1)->cube); for(; temp2 < unretain_nodes ; temp2++) { if(((*temp2)->status & RETAINED) == NULL) continue; if((*temp1) == (*temp2)) continue; if(disjoint_sharp(&temp_cube,(*temp2)->cube)) { foutput_cube_and_links(stderr,(*temp1)); fatal_program_error("a node in the cycle is in fact covered"); } } temp2 = retained_nodes; for(; temp2 < unretain_nodes ; temp2++) { if((*temp2)->status & DECIDED) continue; if((*temp2) == (*temp1)) continue; if(disjoint_sharp(&temp_cube,(*temp2)->cube)) break; } if(temp_cube != NULL) { foutput_cube_and_links(stderr,(*temp1)); fatal_program_error("a node in the cycle is in fact essential"); } } } send_user_message("you indeed seem to have a real cycle"); } /****************************************************************** NAME check_graph PURPOSE check that the graph generated by the function which does generate the prime implicants and the graph, is consistent. SYNOPSIS check_graph() DESCRIPTION We first that for each ancestor of a node, there is a link pointing to the node as a descendant. After we check if all the ancestors can cover the node, if not the node must be basic. Also we check that all the ancestors and descendants of the node do intersect with it. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 9 august 1984 AUTHOR Michel DAGENAIS **************************************************************************/ check_graph() { int nb_nodes, nb_basic, nb_scanned; struct node **temp1, **temp2, *temp_node, *parent_node; struct parent *temp_parent, *parent_parent; struct cube_list *temp_cube; /* We first check the consistancy of the graph */ temp1 = prime_nodes; for(; temp1 < end_prime ; temp1++) { temp_node = *temp1 temp_parent = temp_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { parent_node = temp_parent->parent; parent_parent = parent_node->descendants; for(; parent_parent != NULL ; parent_parent = parent_parent->next_parent) { if(parent_parent->parent == temp_node) break; } if(parent_parent == NULL) { foutput_cube_and_links(stderr,temp_node); fatal_program_error("inconsistancy in the graph"); } } temp_parent = temp_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { parent_node = temp_parent->parent; parent_parent = parent_node->ancestors; for(; parent_parent != NULL ; parent_parent = parent_parent->next_parent) { if(parent_parent->parent == temp_node) break; } if(parent_parent == NULL) { foutput_cube_and_links(stderr,temp_node); fatal_program_error("inconsistancy in the graph"); } } } send_user_message("the graph is consistent"); /* We count the nodes and the basic nodes; Also we check certain properties of the nodes that might not be there but should. */ nb_nodes = 0; nb_basic = 0; temp1 = prime_nodes; for(; temp1 < end_prime ; temp1++) { temp_node = *temp1; nb_nodes++; if(temp_node->status & DONT_CARE) continue; temp_cube = copy_and_alloc_cube_list(temp_node->cube); temp_parent = temp_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { if(disjoint_sharp(&temp_cube,temp_parent->parent->cube))break; } if(temp_cube != NULL) { free_list_of_cubes(&temp_cube); if((temp_node->status & BASIC) == NULL) { foutput_cube_and_links(stderr,temp_node); fatal_program_error("this cube is in fact basic"); } } } temp1 = prime_nodes; for(; temp1 < end_prime ; temp_node = temp1++) { if((*temp1)->status & BASIC) { nb_basic++; } } send_user_message("all nodes uncovered by ancestors are basic"); /* We will now check that all the nodes intersecting are linked together in the graph. */ temp1 = prime_nodes; for(; temp1 < end_prime ; temp1++) { temp_node = *temp1; temp_parent = temp_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { if(intersect(temp_node->cube,temp_parent->parent->cube) == 0) { foutput_cube_and_links(stderr,temp_node); foutput_cube_and_links(stderr,temp_parent->parent); fatal_program_error("the two nodes above are related but disjoint"); } } temp_parent = temp_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { if(intersect(temp_node->cube,temp_parent->parent->cube) == 0) { foutput_cube_and_links(stderr,temp_node); foutput_cube_and_links(stderr,temp_parent->parent); fatal_program_error("the two nodes above are related but disjoint"); } } } temp1 = prime_nodes; for(; temp1 < end_prime ; temp1++) { temp_node = *temp1; current_node = temp_node; scanned_node = temp_node; scan_count = 1; increment_pass_count(); scan_intersecting_ancestors(); current_node = scanned_node; scan_intersecting_descendants(); parent_node = list; nb_scanned = 0; for(; parent_node != NULL ; parent_node = parent_node->next_node) { if(intersect(parent_node->cube,temp_node->cube)) { if((parent_node->count | ONE) != odd_pass_counter) { foutput_cube_and_links(stderr,temp_node); foutput_cube_and_links(stderr,parent_node); fatal_program_error("two nodes intersect but are not related"); } nb_scanned++; } } if(nb_scanned != scan_count) { foutput_cube_and_links(stderr,temp_node); fatal_program_error("some nodes are in the graph but not in the list"); } } sprintf(error_buffer,"your graph is perfect and has %d nodes and %d basic\n", nb_nodes,nb_basic); send_user_message(error_buffer); init_pass_count(); } /************************************************************************ NAME scan_intersecting_ancestors, scan_intersecting_descendants SYNOPSIS scan_intersecting_ancestors(), scan_intersecting_descendants() DESCRIPTION These function scan all the intersecting parents of the current node, set their pass counter and count them. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA AUTHOR Michel DAGENAIS *****************************************************************************/ scan_intersecting_ancestors() { struct parent *temp_parent; temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; if(current_node->count == pass_counter) continue; if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; scan_intersecting_ancestors(); continue; } if(intersect(scanned_node->cube,current_node->cube) == 0)continue; current_node->count = pass_counter; scan_count++; scan_intersecting_ancestors(); current_node = temp_parent->parent; scan_intersecting_descendants(); } } /***************************************************************************/ scan_intersecting_descendants() { struct parent *temp_parent; temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; if((current_node->count | ONE) == odd_pass_counter) continue; if(intersect(current_node->cube,scanned_node->cube) == 0)continue; scan_count++; current_node->count = odd_pass_counter; scan_intersecting_descendants(); } }