#include "cubes.h" /********************************************************************** NAME scan_affected_retained_ancestors, scan_affected_retained_descendants scan_affected_unretain_ancestors, scan_affected_unretain_descendants PURPOSE This recursive function scans all the path in the graph that may contain some nodes that may be affected by the decision taken on a node. If a node is retained, all the undecided nodes that intersect with this node might get completely covered or simply inferior; their uncovered part is updated in the process to take into account the fact that a new node was retained and covers part of it. If a node is unretained, some node might become essential because they would be the only remaining undecided node to cover a yet uncovered part of the function. SYNOPSIS scan_affected_retained_ancestors() scan_affected_retained_descendants() scan_affected_unretain_ancestors() scan_affected_unretain_descendants() DESCRIPTION -scan_affected_retained_ancestors will look at all the ancestors of the current_node. For each of them, if their uncovered part intersects with the scanned_node, it is updated to take into account the fact that the scanned node is being retained. The undecided nodes affected are put on the stack with the status affected_retained. Also when we have intersection, all the ancestors and descendants of the node affected will be recursively scanned. -scan_affected_retained_descendants does the samething but on the descendants of the current node. Also the intersecting descendants only have their descendants recursively scannned. -scan_affected_unretain_ancestors will look to all the ancestors of the current node. For each of them, if their uncovered part intersects with the scanned node they have their ancestors and descendants recursively checked. Also the nodes undecided affected are put on the affected stack to be processed in case we can now get a decision on them. -scan_affected_unretain_descendants does the same but on the descendants of the current node. Also the intersecting descendants only have their intersecting descendants recursively scanned. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 17 july 1984 AUTHOR Michel DAGENAIS *************************************************************************/ scan_affected_retained_descendants() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if((current_node->count | ONE) == odd_pass_counter)continue; /* if the node is covered there is nothing to do on this side */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } /* if the uncovered part of the node intersects with the node retained we will sharp it. */ if(intersect_list(scanned_node->cube,current_node->uncovered)) { current_node->count = odd_pass_counter; if(disjoint_sharp(&(current_node->uncovered),scanned_node->cube)) { current_node->status |= COVERED; } if(current_node->status & DECIDED)scan_affected_retained_descendants(); else /* the node is undecided so if it is not already in the affected stack, we will put it in it. */ { if((current_node->status & AFFECTED) == 0) push(current_node); current_node->status |= AFFECTED_RETAINED; scan_affected_retained_descendants(); } } else current_node->count = pass_counter; } } /****************************************************************************/ scan_affected_retained_ancestors() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if(current_node->count == pass_counter)continue; /* If the node was already scanned for descendants, we will also at this point scan its ancestors. */ if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; scan_affected_retained_ancestors(); continue; } /* if the node is covered there is nothing to do on this side */ current_node->count = pass_counter; if(current_node->status & COVERED) continue; /* if the uncovered part of the node intersects with the node retained we will sharp it. */ if(intersect_list(scanned_node->cube,current_node->uncovered)) { if(disjoint_sharp(&(current_node->uncovered),scanned_node->cube)) { current_node->status |= COVERED; } if(current_node->status & DECIDED) { scan_affected_retained_ancestors(); current_node = temp_parent->parent; scan_affected_retained_descendants(); } else /* the node is undecided so if it is not already in the affected stack, we will put it in it. */ { if((current_node->status & AFFECTED) == 0) push(current_node); current_node->status |= AFFECTED_RETAINED; scan_affected_retained_ancestors(); current_node = temp_parent->parent; scan_affected_retained_descendants(); } } } } /***************************************************************************/ scan_affected_unretain_descendants() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if((current_node->count | ONE) == odd_pass_counter)continue; /* if the node is covered there is nothing to do on this side */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } /* if the uncovered part of the node intersects with the node unretained this part may become essential if this node is the only one not unretained to cover it. */ if(intersect_list(scanned_node->cube,current_node->uncovered)) { current_node->count = odd_pass_counter; if(current_node->status & DECIDED)scan_affected_unretain_descendants(); else /* the node is undecided so if it is not already in the affected stack, we will put it in it. */ { if((current_node->status & AFFECTED) == 0) push(current_node); current_node->status |= AFFECTED_UNRETAIN; scan_affected_unretain_descendants(); } } else current_node->count = pass_counter; } } /***************************************************************************/ scan_affected_unretain_ancestors() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if(current_node->count == pass_counter)continue; /* if the node was already scanned for descendants we will now at this point scan it for ancestors. */ if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; scan_affected_unretain_ancestors(); continue; } current_node->count = pass_counter; /* if the node is covered there is nothing to do on this side */ if(current_node->status & COVERED)continue; /* if the uncovered part of the node intersects with the node unretained this part may become essential if this node is the only one not unretained to cover it. */ if(intersect_list(scanned_node->cube,current_node->uncovered)) { if(current_node->status & DECIDED) { scan_affected_unretain_ancestors(); current_node = temp_parent->parent; scan_affected_unretain_descendants(); } else /* the node is undecided so if it is not already in the affected stack, we will put it in it. */ { if((current_node->status & AFFECTED) == 0) push(current_node); current_node->status |= AFFECTED_UNRETAIN; scan_affected_unretain_ancestors(); current_node = temp_parent->parent; scan_affected_unretain_descendants(); } } } } /***************************************************************************** NAME scan_inferior_descendants, scan_inferior_ancestors PURPOSE Determine if the uncovered part of a cube by retained cubes can be covered by a single unretained cube of lower or equal cost, in which case, the scanned cube is inferior. SYNOPSIS int scan_inferior_descendants() int scan_inferior_ancestors() DESCRIPTION -scan_inferior_descendants, for each descendants of the current node, we look if they are undecided and can cover the uncovered part of the scanned node. If the cube is of lower or equal cost then the scanned node, we unretain inferior the scanned node. If the node is of greater cost and covers, if we dont ask for minimum number of literals, we will unretain inferior the scanned node just as well. If the descendants examined is undecided inferior or if it is undecided but of greater cost, we will scan its descendants recursively. -scan_inferior_ancestors does the same but on the ancestors. Also the recursive scanning is on both the ancestors and descendants. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 17 july 1984 AUTHOR Michel DAGENAIS *************************************************************************/ int scan_inferior_descendants() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or the scanned node to avoid passing many times on some node on the graph. */ if((current_node->count | ONE) == odd_pass_counter)continue; /* If the node is covered by retained cubes, we can ignore it since it was sharped from the scanned cube in the scan covering pass */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } if(intersect_list(current_node->cube,scanned_node->uncovered)) { current_node->count = odd_pass_counter; if(current_node->status & DECIDED) /* the node is unretained but covers the uncovered part of the scanned_node so maybe one of its parents is undecided and also covers it and we must scan them. */ { if(scan_inferior_descendants()) return(1); } /* if the node is undecided and covers the scanned cube and has a lower cost then the scanned cube is unretained inferior. */ else if(covers_list(current_node->cube,scanned_node->uncovered)) { if(current_node->cost <= scanned_node->cost || DONT_MIN_LITERAL) { #ifdef CHECK unretain_inferior_check_node(); #else unretain_inferior_node(); #endif return(1); } else if(scan_inferior_descendants()) return(1); } else { if(scan_inferior_descendants()) return(1); } } else current_node->count = pass_counter; } return(0); } /**************************************************************************/ int scan_inferior_ancestors() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or the scanned node to avoid passing many times on some node on the graph. */ if(current_node->count == pass_counter)continue; if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; if(scan_inferior_ancestors()) return(1); continue; } current_node->count = pass_counter; /* If the node is covered by retained cubes, we can ignore it since it was sharped from the scanned cube in the scan covering pass */ if(current_node->status & COVERED) continue; if(intersect_list(current_node->cube,scanned_node->uncovered)) { if(current_node->status & DECIDED) /* the node is unretained but covers the uncovered part of the scanned_node so maybe one of its parents is undecided and also covers it and we must scan them. */ { if(scan_inferior_ancestors()) return(1); current_node = temp_parent->parent; if(scan_inferior_descendants()) return(1); } /* if the node is undecided and covers the scanned cube and has a lower cost then the scanned cube is unretained inferior. */ else if(covers_list(current_node->cube,scanned_node->uncovered)) { if(current_node->cost <= scanned_node->cost || DONT_MIN_LITERAL) { #ifdef CHECK unretain_inferior_check_node(); #else unretain_inferior_node(); #endif return(1); } else { if(scan_inferior_ancestors()) return(1); current_node = temp_parent->parent; if(scan_inferior_descendants()) return(1); } } else { if(scan_inferior_ancestors()) return(1); current_node = temp_parent->parent; if(scan_inferior_descendants()) return(1); } } } return(0); } /*********************************************************************** NAME scan_essential_descendants, scan_essential_ancestors PURPOSE Determine if the uncovered part of the scanned node can be covered by an undecided node, if not the scanned node must be retained. SYNOPSIS int scan_essential_descendants() int scan_essential_ancestors() DESCRIPTION The parent nodes are scanned to see if the uncovered part can be covered by the undecided cubes. Scanned_cube contains the part of scanned_node not covered by any retained or undecided node. The parents of the current node which are undecided are sharped from the scanned_cube; The parents unretained inferior intersecting with the scanned cube are scanned recursively in case one of their parent would intersect with scanned cube and be undecided. -scan_essential_descendants examines the descendants of the current node and scans recursively the intersecting inferior nodes. -scan_essential_ancestors does the same on the ancestors of the current node. Also the ancestors and descendants are scanned recursively. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 17 july 1984 AUTHOR Michel DAGENAIS *************************************************************************/ int scan_essential_descendants() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or the scanned node to avoid passing many times on some node on the graph. */ if((current_node->count | ONE) == odd_pass_counter)continue; /* If the node is covered by retained cubes, we can ignore it since it was sharped from the scanned cube in the scan covering pass */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } if(intersect_list(current_node->cube,scanned_cube)) { if(current_node->status & DECIDED) /* the node is unretained but covers a part of the scanned_node so maybe one of its parents is undecided and also covers it and we must scan them. */ { current_node->count = odd_pass_counter; if(scan_essential_descendants())return(1); } /* if the node is undecided and covers a part of the scanned cube we sharp it and see if any uncovered part remains. */ else { current_node->count = pass_counter; if(disjoint_sharp(&scanned_cube,current_node->cube)) return(1); } } else current_node->count = pass_counter; } return(0); } /**************************************************************************/ int scan_essential_ancestors() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or the scanned node to avoid passing many times on some node on the graph. */ if(current_node->count == pass_counter)continue; if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; if(scan_essential_ancestors()) return(1); continue; } current_node->count = pass_counter; /* If the node is covered by retained cubes, we can ignore it since it was sharped from the scanned cube in the scan covering pass */ if(current_node->status & COVERED) continue; if(intersect_list(current_node->cube,scanned_cube)) { if(current_node->status & DECIDED) /* the node is unretained but covers a part of the scanned_node so maybe one of its parents is undecided and also covers it and we must scan them. */ { if(scan_essential_ancestors())return(1); current_node = temp_parent->parent; if(scan_essential_descendants()) return(1); } /* if the node is undecided and covers a part of the scanned cube we sharp it and see if any uncovered part remains. */ else { if(disjoint_sharp(&scanned_cube,current_node->cube)) return(1); } } } return(0); } /************************************************************************* NAME scan_partition PURPOSE When we have a cycle we want to put in a partition only the nodes that can interact with each other. Two nodes can interact with each other when their respective uncovered part do intersect. So in a partition we put together all the nodes undecided or inferior such that each node is related directly or indirectly to the starting node. SYNOPSIS scan_partition() DESCRIPTION All the nodes which can affect the current node have their pass count set to the pass counter and they are recursively scanned. Also, each node put this way in the partition is counted in scan_count. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 17 july 1984 AUTHOR Michel DAGENAIS ****************************************************************************/ scan_partition() { struct parent *temp_parent; /* parent to inspect */ struct node *save_current_node; /* current node saved during scanning */ /* we will now scan its ancestors to find uncovered nodes to scan */ save_current_node = current_node; 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 the node is covered by retained cubes, we can ignore it since it does cut the interactions with the other cubes related to it. */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } /* it is a undecided or inferior node it will be scanned for partition */ if(intersect_list(current_node->cube,save_current_node->uncovered)) { current_node->count = pass_counter; scan_count++; scan_partition(); } } /* we will now scan its descendants to find uncovered nodes to scan */ temp_parent = save_current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; if(current_node->count == pass_counter)continue; /* If the node is covered by retained cubes, we can ignore it since it does cut the interactions with the other cubes related to it. */ if(current_node->status & COVERED) { current_node->count = pass_counter; continue; } /* it is a undecided or inferior node it will be scanned for partition */ if(intersect_list(current_node->cube,save_current_node->uncovered)) { current_node->count = pass_counter; scan_count++; scan_partition(); } } } /************************************************************************** NAME scan_sparse_ancestors, scan_sparse_descendants PURPOSE Find all the other retained cubes intersecting with a retained cube, to sharp them and determine which part is uniquely covered by each retained cube. SYNOPSIS scan_sparse_ancestors() scan_sparse_descendants() DESCRIPTION -scan_sparse_ancestors, the ancestors of the current node are examined, the retained nodes are sharped from the scanned cube. The other nodes intersecting with the scanned cube have their ancestors and descendants recursively scanned. -scan_sparse_descendants does the same but for the descendants of the current node. Also the recursive scan is done only on the descendants. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 14 august 1984 AUTHOR Michel DAGENAIS *************************************************************************/ scan_sparse_descendants() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->descendants; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if((current_node->count | ONE) == odd_pass_counter)continue; /* The node is retained, we will sharp it from the scanned cube */ if(current_node->status & RETAINED) { (void)disjoint_sharp(&scanned_cube,current_node->cube); current_node->count = pass_counter; continue; } if(intersect_list(current_node->cube,scanned_cube)) { current_node->count = odd_pass_counter; scan_sparse_descendants(); } else current_node->count = pass_counter; } } /****************************************************************************/ scan_sparse_ancestors() { struct parent *temp_parent; /* parent to inspect */ temp_parent = current_node->ancestors; for(; temp_parent != NULL ; temp_parent = temp_parent->next_parent) { current_node = temp_parent->parent; /* we must check that we do not come back to either the calling node or a node already scanned to avoid passing many times on some node on the graph. */ if(current_node->count == pass_counter)continue; /* If the node was already scanned for descendants, we will also at this point scan its ancestors. */ if(current_node->count == odd_pass_counter) { current_node->count = pass_counter; scan_sparse_ancestors(); continue; } current_node->count = pass_counter; if(current_node->status & RETAINED) { (void)disjoint_sharp(&scanned_cube,current_node->cube); continue; } if(intersect_list(scanned_node->cube,current_node->uncovered)) { scan_sparse_ancestors(); current_node = temp_parent->parent; scan_sparse_descendants(); } } }