1 /*========================================================================
2 	       Copyright (C) 1996-2002 by Jorn Lind-Nielsen
3 			    All rights reserved
4 
5     Permission is hereby granted, without written agreement and without
6     license or royalty fees, to use, reproduce, prepare derivative
7     works, distribute, and display this software and its documentation
8     for any purpose, provided that (1) the above copyright notice and
9     the following two paragraphs appear in all copies of the source code
10     and (2) redistributions, including without limitation binaries,
11     reproduce these notices in the supporting documentation. Substantial
12     modifications to this software may be copyrighted by their authors
13     and need not follow the licensing terms described here, provided
14     that the new terms are clearly indicated in all files where they apply.
15 
16     IN NO EVENT SHALL JORN LIND-NIELSEN, OR DISTRIBUTORS OF THIS
17     SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
18     INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
19     SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE
20     ABOVE PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 
22     JORN LIND-NIELSEN SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
23     BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24     FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
25     ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
26     OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
27     MODIFICATIONS.
28 ========================================================================*/
29 
30 /*************************************************************************
31   $Header: /Volumes/CVS/repository/spot/spot/buddy/src/pairs.c,v 1.7 2003/05/22 15:07:27 aduret Exp $
32   FILE:  pairs.c
33   DESCR: Pair management for BDD package.
34   AUTH:  Jorn Lind
35   DATE:  february 1997
36 *************************************************************************/
37 #include <stdlib.h>
38 #include <limits.h>
39 #include "kernel.h"
40 
41 /*======================================================================*/
42 
43 static int      pairsid;            /* Pair identifier */
44 static bddPair* pairs;              /* List of all replacement pairs in use */
45 
46 
47 /*************************************************************************
48 *************************************************************************/
49 
bdd_pairs_init(void)50 void bdd_pairs_init(void)
51 {
52    pairsid = 0;
53    pairs = NULL;
54 }
55 
56 
bdd_pairs_done(void)57 void bdd_pairs_done(void)
58 {
59    bddPair *p = pairs;
60    int n;
61 
62    while (p != NULL)
63    {
64       bddPair *next = p->next;
65       for (n=0 ; n<bddvarnum ; n++)
66 	 bdd_delref( p->result[n] );
67       free(p->result);
68       free(p);
69       p = next;
70    }
71 }
72 
73 
update_pairsid(void)74 static int update_pairsid(void)
75 {
76    pairsid++;
77 
78    if (pairsid == (INT_MAX >> 2))
79    {
80       bddPair *p;
81       pairsid = 0;
82       for (p=pairs ; p!=NULL ; p=p->next)
83 	 p->id = pairsid++;
84       bdd_operator_reset();
85    }
86 
87    return pairsid;
88 }
89 
90 
bdd_register_pair(bddPair * p)91 void bdd_register_pair(bddPair *p)
92 {
93    p->next = pairs;
94    pairs = p;
95 }
96 
97 
bdd_pairs_vardown(int level)98 void bdd_pairs_vardown(int level)
99 {
100    bddPair *p;
101 
102    for (p=pairs ; p!=NULL ; p=p->next)
103    {
104       int tmp;
105 
106       tmp = p->result[level];
107       p->result[level] = p->result[level+1];
108       p->result[level+1] = tmp;
109 
110       if (p->last == level)
111 	 p->last++;
112    }
113 }
114 
115 
bdd_pairalloc(void)116 static bddPair *bdd_pairalloc(void)
117 {
118    bddPair *p;
119    if ((p=(bddPair*)malloc(sizeof(bddPair))) == NULL)
120    {
121       bdd_error(BDD_MEMORY);
122       return NULL;
123    }
124 
125    if ((p->result=(BDD*)malloc(sizeof(BDD)*bddvarnum)) == NULL)
126    {
127       free(p);
128       bdd_error(BDD_MEMORY);
129       return NULL;
130    }
131    return p;
132 }
133 
134 
bdd_pairs_resize(int oldsize,int newsize)135 int bdd_pairs_resize(int oldsize, int newsize)
136 {
137    bddPair *p;
138    int n;
139 
140    for (p=pairs ; p!=NULL ; p=p->next)
141    {
142       if ((p->result=(BDD*)realloc(p->result,sizeof(BDD)*newsize)) == NULL)
143 	 return bdd_error(BDD_MEMORY);
144 
145       for (n=oldsize ; n<newsize ; n++)
146 	 p->result[n] = bdd_ithvar(bddlevel2var[n]);
147    }
148 
149    return 0;
150 }
151 
152 
153 /*
154 NAME    {* bdd\_newpair *}
155 SECTION {* kernel *}
156 SHORT   {* creates an empty variable pair table *}
157 PROTO   {* bddPair *bdd_newpair(void) *}
158 DESCR   {* Variable pairs of the type {\tt bddPair} are used in
159 	   {\tt bdd\_replace} to define which variables to replace with
160 	   other variables. This function allocates such an empty table. The
161 	   table can be freed by a call to {\tt bdd\_freepair}. *}
162 RETURN  {* Returns a new table of pairs. *}
163 ALSO    {* bdd\_freepair, bdd\_replace, bdd\_setpair, bdd\_setpairs *}
164 */
bdd_newpair(void)165 bddPair *bdd_newpair(void)
166 {
167    int n;
168    bddPair *p;
169 
170    p = bdd_pairalloc();
171    if (p == NULL)
172      return NULL;
173 
174    for (n=0 ; n<bddvarnum ; n++)
175       p->result[n] = bdd_ithvar(bddlevel2var[n]);
176 
177    p->id = update_pairsid();
178    p->last = -1;
179 
180    bdd_register_pair(p);
181    return p;
182 }
183 
184 
185 /*
186 NAME    {* bdd\_copypair *}
187 SECTION {* kernel *}
188 SHORT   {* clone a pair table *}
189 PROTO   {* bddPair *bdd_copypair(bddPair *from) *}
190 DESCR   {* Duplicate the table of pairs {\tt from}.
191 	   This function allocates the cloned table. The
192 	   table can be freed by a call to {\tt bdd\_freepair}. *}
193 RETURN  {* Returns a new table of pairs. *}
194 ALSO    {* bdd\_newpair, bdd\_freepair, bdd\_replace, bdd\_setpair, bdd\_setpairs *}
195 */
bdd_copypair(bddPair * from)196 bddPair *bdd_copypair(bddPair *from)
197 {
198    int n;
199    bddPair *p;
200 
201    p = bdd_pairalloc();
202    if (p == NULL)
203      return NULL;
204 
205    for (n=0 ; n<bddvarnum ; n++)
206      p->result[n] = bdd_addref(from->result[n]);
207 
208    p->id = update_pairsid();
209    p->last = from->last;
210 
211    bdd_register_pair(p);
212    return p;
213 }
214 
215 /*
216 NAME    {* bdd\_mergepairs *}
217 SECTION {* kernel *}
218 SHORT   {* merge two pair tables *}
219 PROTO   {* bddPair *bdd_mergepairs(bddPair *left, bddPairs *right) *}
220 DESCR   {* Create a table of pairs that can be used to perform the
221 	   rewritings of both {\tt left} and {\tt right}.  This cannot work if
222 	   the two tables contain incompatible rewrite pairs (for instance
223 	   if left rewrite 1 to 2, and right rewrite 1 to 3).
224 
225 	   This function allocates a new table. The
226 	   table can be freed by a call to {\tt bdd\_freepair}. *}
227 RETURN  {* Returns a new table of pairs. *}
228 ALSO    {* bdd\_newpair, bdd\_freepair, bdd\_replace, bdd\_setpair, bdd\_setpairs *}
229 */
bdd_mergepairs(bddPair * left,bddPair * right)230 bddPair *bdd_mergepairs(bddPair *left, bddPair *right)
231 {
232    int n;
233    bddPair *p;
234 
235    p = bdd_copypair(left);
236    if (p == NULL)
237      return NULL;
238 
239    for (n=0; n<bddvarnum; n++)
240      {
241        bdd nl = bdd_ithvar(n);
242 
243        /* If P performs no rewriting for N, blindly use that of RIGHT.  */
244        if (nl == p->result[n])
245 	 {
246 	   bdd_delref(p->result[n]);
247 	   p->result[n] = bdd_addref(right->result[n]);
248 	 }
249        else
250 	 /* If P rewrites N, make sure RIGHT doesn't rewrite it, or that
251 	    it rewrites it to the same variable.  */
252 	 if (nl != right->result[n] && right->result[n] != p->result[n])
253 	   {
254 	     bdd_freepair(p);
255 	     bdd_error(BDD_INVMERGE);
256 	     return NULL;
257 	   }
258      }
259 
260    if (p->last < right->last)
261      p->last = right->last;
262 
263    /* We don't have to update the ID, because this pair was not
264       used since bdd_copypair were called. */
265    return p;
266 }
267 
268 
269 /*
270 NAME    {* bdd\_setpair *}
271 EXTRA   {* bdd\_setbddpair *}
272 SECTION {* kernel *}
273 SHORT   {* set one variable pair *}
274 PROTO   {* int bdd_setpair(bddPair *pair, int oldvar, int newvar)
275 int bdd_setbddpair(bddPair *pair, int oldvar, BDD newvar) *}
276 DESCR   {* Adds the pair {\tt (oldvar,newvar)} to the table of pairs
277 	   {\tt pair}. This results in {\tt oldvar} being substituted
278 	   with {\tt newvar} in a call to {\tt bdd\_replace}. In the first
279 	   version {\tt newvar} is an integer representing the variable
280 	   to be replaced with the old variable.
281 	   In the second version {\tt oldvar} is a BDD.
282 	   In this case the variable {\tt oldvar} is substituted with the
283 	   BDD {\tt newvar}.
284 	   The possibility to substitute with any BDD as {\tt newvar} is
285 	   utilized in bdd\_compose, whereas only the topmost variable
286 	   in the BDD is used in bdd\_replace. *}
287 RETURN  {* Zero on success, otherwise a negative error code. *}
288 ALSO    {* bdd\_newpair, bdd\_setpairs, bdd\_resetpair, bdd\_replace, bdd\_compose *}
289 */
bdd_setpair(bddPair * pair,int oldvar,int newvar)290 int bdd_setpair(bddPair *pair, int oldvar, int newvar)
291 {
292    if (pair == NULL)
293       return 0;
294 
295    if (oldvar < 0  ||  oldvar > bddvarnum-1)
296       return bdd_error(BDD_VAR);
297    if (newvar < 0  ||  newvar > bddvarnum-1)
298       return bdd_error(BDD_VAR);
299 
300    bdd_delref( pair->result[bddvar2level[oldvar]] );
301    pair->result[bddvar2level[oldvar]] = bdd_ithvar(newvar);
302    pair->id = update_pairsid();
303 
304    if (bddvar2level[oldvar] > pair->last)
305       pair->last = bddvar2level[oldvar];
306 
307    return 0;
308 }
309 
310 
bdd_setbddpair(bddPair * pair,int oldvar,BDD newvar)311 int bdd_setbddpair(bddPair *pair, int oldvar, BDD newvar)
312 {
313    int oldlevel;
314 
315    if (pair == NULL)
316       return 0;
317 
318    CHECK(newvar);
319    if (oldvar < 0  ||  oldvar >= bddvarnum)
320       return bdd_error(BDD_VAR);
321    oldlevel = bddvar2level[oldvar];
322 
323    bdd_delref( pair->result[oldlevel] );
324    pair->result[oldlevel] = bdd_addref(newvar);
325    pair->id = update_pairsid();
326 
327    if (oldlevel > pair->last)
328       pair->last = oldlevel;
329 
330    return 0;
331 }
332 
333 
334 /*
335 NAME    {* bdd\_setpairs *}
336 EXTRA   {* bdd\_setbddpairs *}
337 SECTION {* kernel *}
338 SHORT   {* defines a whole set of pairs *}
339 PROTO   {* int bdd_setpairs(bddPair *pair, int *oldvar, int *newvar, int size)
340 int bdd_setbddpairs(bddPair *pair, int *oldvar, BDD *newvar, int size) *}
341 DESCR   {* As for {\tt bdd\_setpair} but with {\tt oldvar} and {\tt newvar}
342 	   being arrays of variables (BDDs) of size {\tt size}. *}
343 RETURN  {* Zero on success, otherwise a negative error code. *}
344 ALSO    {* bdd\_newpair, bdd\_setpair, bdd\_replace, bdd\_compose *}
345 */
bdd_setpairs(bddPair * pair,int * oldvar,int * newvar,int size)346 int bdd_setpairs(bddPair *pair, int *oldvar, int *newvar, int size)
347 {
348    int n,e;
349    if (pair == NULL)
350       return 0;
351 
352    for (n=0 ; n<size ; n++)
353       if ((e=bdd_setpair(pair, oldvar[n], newvar[n])) < 0)
354 	 return e;
355 
356    return 0;
357 }
358 
359 
bdd_setbddpairs(bddPair * pair,int * oldvar,BDD * newvar,int size)360 int bdd_setbddpairs(bddPair *pair, int *oldvar, BDD *newvar, int size)
361 {
362    int n,e;
363    if (pair == NULL)
364       return 0;
365 
366    for (n=0 ; n<size ; n++)
367       if ((e=bdd_setbddpair(pair, oldvar[n], newvar[n])) < 0)
368 	 return e;
369 
370    return 0;
371 }
372 
373 
374 /*
375 NAME    {* bdd\_freepair *}
376 SECTION {* kernel *}
377 SHORT   {* frees a table of pairs *}
378 PROTO   {* void bdd_freepair(bddPair *pair) *}
379 DESCR   {* Frees the table of pairs {\tt pair} that has been allocated
380 	   by a call to {\tt bdd\_newpair}. *}
381 ALSO    {* bdd\_replace, bdd\_newpair, bdd\_setpair, bdd\_resetpair *}
382 */
bdd_freepair(bddPair * p)383 void bdd_freepair(bddPair *p)
384 {
385    int n;
386 
387    if (p == NULL)
388       return;
389 
390    if (pairs != p)
391    {
392       bddPair *bp = pairs;
393       while (bp != NULL  &&  bp->next != p)
394 	 bp = bp->next;
395 
396       if (bp != NULL)
397 	 bp->next = p->next;
398    }
399    else
400       pairs = p->next;
401 
402    for (n=0 ; n<bddvarnum ; n++)
403       bdd_delref( p->result[n] );
404    free(p->result);
405    free(p);
406 }
407 
408 
409 /*
410 NAME    {* bdd\_resetpair *}
411 SECTION {* kernel *}
412 SHORT   {* clear all variable pairs *}
413 PROTO   {* void bdd_resetpair(bddPair *pair) *}
414 DESCR   {* Resets the table of pairs {\tt pair} by setting all substitutions
415 	   to their default values (that is no change). *}
416 ALSO    {* bdd\_newpair, bdd\_setpair, bdd\_freepair *}
417 */
bdd_resetpair(bddPair * p)418 void bdd_resetpair(bddPair *p)
419 {
420    int n;
421 
422    for (n=0 ; n<bddvarnum ; n++)
423       p->result[n] = bdd_ithvar(n);
424    p->last = 0;
425 }
426 
427 
428 /* EOF */
429