You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							452 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							452 lines
						
					
					
						
							12 KiB
						
					
					
				| /**CFile********************************************************************** | |
|  | |
|   FileName     [dddmpNodeBdd.c] | |
|  | |
|   PackageName  [dddmp] | |
|  | |
|   Synopsis     [Functions to handle BDD node infos and numbering] | |
|  | |
|   Description  [Functions to handle BDD node infos and numbering. | |
|     ] | |
|  | |
|   Author       [Gianpiero Cabodi and Stefano Quer] | |
|  | |
|   Copyright    [ | |
|     Copyright (c) 2004 by Politecnico di Torino. | |
|     All Rights Reserved. This software is for educational purposes only. | |
|     Permission is given to academic institutions to use, copy, and modify | |
|     this software and its documentation provided that this introductory | |
|     message is not removed, that this software and its documentation is | |
|     used for the institutions' internal research and educational purposes, | |
|     and that no monies are exchanged. No guarantee is expressed or implied | |
|     by the distribution of this code. | |
|     Send bug-reports and/or questions to: | |
|     {gianpiero.cabodi,stefano.quer}@polito.it. | |
|     ] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "dddmpInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static int NumberNodeRecurBdd(DdNode *f, int id); | |
| static void RemoveFromUniqueRecurBdd(DdManager *ddMgr, DdNode *f); | |
| static void RestoreInUniqueRecurBdd(DdManager *ddMgr, DdNode *f); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes nodes from unique table and number them] | |
|  | |
|   Description [Node numbering is required to convert pointers to integers. | |
|     Since nodes are removed from unique table, no new nodes should  | |
|     be generated before re-inserting nodes in the unique table | |
|     (DddmpUnnumberBddNodes ()). | |
|     ] | |
|  | |
|   SideEffects [Nodes are temporarily removed from unique table] | |
|  | |
|   SeeAlso     [RemoveFromUniqueRecur(), NumberNodeRecur(),  | |
|     DddmpUnnumberBddNodes ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpNumberBddNodes ( | |
|   DdManager *ddMgr  /* IN: DD Manager */, | |
|   DdNode **f        /* IN: array of BDDs */, | |
|   int n             /* IN: number of BDD roots in the array of BDDs */ | |
|   ) | |
| { | |
|   int id=0, i; | |
| 
 | |
|   for (i=0; i<n; i++) { | |
|     RemoveFromUniqueRecurBdd (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   for (i=0; i<n; i++) { | |
|     id = NumberNodeRecurBdd (f[i], id); | |
|   } | |
| 
 | |
|   return (id); | |
| } | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Restores nodes in unique table, loosing numbering] | |
|  | |
|   Description  [Node indexes are no more needed. Nodes are re-linked in the | |
|     unique table. | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpNumberBddNode ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void | |
| DddmpUnnumberBddNodes( | |
|   DdManager *ddMgr  /* IN: DD Manager */, | |
|   DdNode **f        /* IN: array of BDDs */, | |
|   int n             /* IN: number of BDD roots in the array of BDDs */ | |
|   ) | |
| { | |
|   int i; | |
| 
 | |
|   for (i=0; i<n; i++) { | |
|     RestoreInUniqueRecurBdd (ddMgr, f[i]); | |
|   } | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Write index to node] | |
|  | |
|   Description  [The index of the node is written in the "next" field of | |
|     a DdNode struct. LSB is not used (set to 0). It is used as  | |
|     "visited" flag in DD traversals. | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpReadNodeIndexBdd(), DddmpSetVisitedBdd (), | |
|     DddmpVisitedBdd ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void  | |
| DddmpWriteNodeIndexBdd ( | |
|   DdNode *f   /* IN: BDD node */, | |
|   int id       /* IN: index to be written */ | |
|   ) | |
| { | |
|   if (!Cudd_IsConstant (f)) { | |
|     f->next = (struct DdNode *)((ptruint)id<<1); | |
|   } | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Reads the index of a node] | |
|  | |
|   Description  [Reads the index of a node. LSB is skipped (used as visited | |
|     flag). | |
|     ] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpWriteNodeIndexBdd (), DddmpSetVisitedBdd (), | |
|     DddmpVisitedBdd ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpReadNodeIndexBdd ( | |
|   DdNode *f    /* IN: BDD node */ | |
|   ) | |
| { | |
|   if (!Cudd_IsConstant (f)) { | |
|     return ((int)(((ptruint)(f->next))>>1)); | |
|   } else { | |
|     return (1); | |
|   } | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Returns true if node is visited] | |
|  | |
|   Description  [Returns true if node is visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpSetVisitedBdd (), DddmpClearVisitedBdd ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| int | |
| DddmpVisitedBdd ( | |
|   DdNode *f    /* IN: BDD node to be tested */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   return ((int)((ptruint)(f->next)) & (01)); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Marks a node as visited] | |
|   | |
|   Description  [Marks a node as visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpVisitedBdd (), DddmpClearVisitedBdd ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void | |
| DddmpSetVisitedBdd ( | |
|   DdNode *f   /* IN: BDD node to be marked (as visited) */ | |
|   ) | |
| { | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Marks a node as not visited] | |
|  | |
|   Description  [Marks a node as not visited] | |
|  | |
|   SideEffects  [None] | |
|  | |
|   SeeAlso      [DddmpVisited (), DddmpSetVisited ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| void | |
| DddmpClearVisitedBdd ( | |
|   DdNode *f    /* IN: BDD node to be marked (as not visited) */ | |
|   ) | |
| { | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Number nodes recursively in post-order] | |
|  | |
|   Description  [Number nodes recursively in post-order. | |
|     The "visited" flag is used with inverse polarity, because all nodes | |
|     were set "visited" when removing them from unique.  | |
|     ] | |
|  | |
|   SideEffects  ["visited" flags are reset.] | |
|  | |
|   SeeAlso      [] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static int | |
| NumberNodeRecurBdd ( | |
|   DdNode *f  /*  IN: root of the BDD to be numbered */, | |
|   int id     /* IN/OUT: index to be assigned to the node */ | |
|   ) | |
| { | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   if (!DddmpVisitedBdd (f)) { | |
|     return (id); | |
|   } | |
| 
 | |
|   if (!cuddIsConstant (f)) { | |
|     id = NumberNodeRecurBdd (cuddT (f), id); | |
|     id = NumberNodeRecurBdd (cuddE (f), id); | |
|   } | |
| 
 | |
|   DddmpWriteNodeIndexBdd (f, ++id); | |
|   DddmpClearVisitedBdd (f); | |
| 
 | |
|   return (id); | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes a node from unique table] | |
|  | |
|   Description [Removes a node from the unique table by locating the proper | |
|     subtable and unlinking the node from it. It recurs on the  | |
|     children of the node. Constants remain untouched. | |
|     ] | |
|  | |
|   SideEffects [Nodes are left with the "visited" flag true.] | |
|  | |
|   SeeAlso     [RestoreInUniqueRecurBdd ()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| RemoveFromUniqueRecurBdd ( | |
|   DdManager *ddMgr  /*  IN: DD Manager */, | |
|   DdNode *f         /*  IN: root of the BDD to be extracted */ | |
|   ) | |
| { | |
|   DdNode *node, *last, *next; | |
|   DdNode *sentinel = &(ddMgr->sentinel); | |
|   DdNodePtr *nodelist; | |
|   DdSubtable *subtable; | |
|   int pos, level; | |
| 
 | |
|   f = Cudd_Regular (f); | |
| 
 | |
|   if (DddmpVisitedBdd (f)) { | |
|     return; | |
|   } | |
| 
 | |
|   if (!cuddIsConstant (f)) { | |
| 
 | |
|     RemoveFromUniqueRecurBdd (ddMgr, cuddT (f)); | |
|     RemoveFromUniqueRecurBdd (ddMgr, cuddE (f)); | |
| 
 | |
|     level = ddMgr->perm[f->index]; | |
|     subtable = &(ddMgr->subtables[level]); | |
| 
 | |
|     nodelist = subtable->nodelist; | |
| 
 | |
|     pos = ddHash (cuddT (f), cuddE (f), subtable->shift); | |
|     node = nodelist[pos]; | |
|     last = NULL; | |
|     while (node != sentinel) { | |
|       next = node->next; | |
|       if (node == f) { | |
|         if (last != NULL)   | |
|   	  last->next = next; | |
|         else  | |
|           nodelist[pos] = next; | |
|         break; | |
|       } else { | |
|         last = node; | |
|         node = next; | |
|       } | |
|     } | |
| 
 | |
|     f->next = NULL; | |
| 
 | |
|   } | |
| 
 | |
|   DddmpSetVisitedBdd (f); | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis     [Restores a node in unique table] | |
|  | |
|   Description  [Restores a node in unique table (recursively)] | |
|  | |
|   SideEffects  [Nodes are not restored in the same order as before removal] | |
|  | |
|   SeeAlso      [RemoveFromUnique()] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| static void | |
| RestoreInUniqueRecurBdd ( | |
|   DdManager *ddMgr /*  IN: DD Manager */, | |
|   DdNode *f        /*  IN: root of the BDD to be restored */ | |
|   ) | |
| { | |
|   DdNodePtr *nodelist; | |
|   DdNode *T, *E, *looking; | |
|   DdNodePtr *previousP; | |
|   DdSubtable *subtable; | |
|   int pos, level; | |
| #ifdef DDDMP_DEBUG | |
|   DdNode *node; | |
|   DdNode *sentinel = &(ddMgr->sentinel); | |
| #endif | |
|  | |
|   f = Cudd_Regular(f); | |
| 
 | |
|   if (!Cudd_IsComplement (f->next)) { | |
|     return; | |
|   } | |
| 
 | |
|   if (cuddIsConstant (f)) { | |
|     /* StQ 11.02.2004: | |
|        Bug fixed --> restore NULL within the next field */ | |
|     /*DddmpClearVisitedBdd (f);*/    | |
|     f->next = NULL; | |
| 
 | |
|     return; | |
|   } | |
| 
 | |
|   RestoreInUniqueRecurBdd (ddMgr, cuddT (f)); | |
|   RestoreInUniqueRecurBdd (ddMgr, cuddE (f)); | |
| 
 | |
|   level = ddMgr->perm[f->index]; | |
|   subtable = &(ddMgr->subtables[level]); | |
| 
 | |
|   nodelist = subtable->nodelist; | |
| 
 | |
|   pos = ddHash (cuddT (f), cuddE (f), subtable->shift); | |
| 
 | |
| #ifdef DDDMP_DEBUG | |
|   /* verify uniqueness to avoid duplicate nodes in unique table */ | |
|   for (node=nodelist[pos]; node != sentinel; node=node->next) | |
|     assert(node!=f); | |
| #endif | |
|  | |
|   T = cuddT (f); | |
|   E = cuddE (f); | |
|   previousP = &(nodelist[pos]); | |
|   looking = *previousP; | |
| 
 | |
|   while (T < cuddT (looking)) { | |
|     previousP = &(looking->next); | |
|     looking = *previousP; | |
|   } | |
| 
 | |
|   while (T == cuddT (looking) && E < cuddE (looking)) { | |
|     previousP = &(looking->next); | |
|     looking = *previousP; | |
|   } | |
| 
 | |
|   f->next = *previousP; | |
|   *previousP = f; | |
| 
 | |
|   return; | |
| } | |
| 
 | |
| 
 |