1 | /* BDD variable association routines */ |
---|
2 | |
---|
3 | |
---|
4 | #include "bddint.h" |
---|
5 | |
---|
6 | |
---|
7 | static |
---|
8 | int |
---|
9 | cmu_bdd_assoc_eq(cmu_bdd_manager bddm, bdd *p, bdd *q) |
---|
10 | { |
---|
11 | bdd_indexindex_type i; |
---|
12 | |
---|
13 | for (i=0; i < bddm->maxvars; ++i) |
---|
14 | if (p[i+1] != q[i+1]) |
---|
15 | return (0); |
---|
16 | return (1); |
---|
17 | } |
---|
18 | |
---|
19 | |
---|
20 | static |
---|
21 | int |
---|
22 | check_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs) |
---|
23 | { |
---|
24 | bdd_check_array(assoc_info); |
---|
25 | if (pairs) |
---|
26 | while (assoc_info[0] && assoc_info[1]) |
---|
27 | { |
---|
28 | if (cmu_bdd_type_aux(bddm, assoc_info[0]) != BDD_TYPE_POSVAR) |
---|
29 | { |
---|
30 | cmu_bdd_warning("check_assoc: first element in pair is not a positive variable"); |
---|
31 | return (0); |
---|
32 | } |
---|
33 | assoc_info+=2; |
---|
34 | } |
---|
35 | return (1); |
---|
36 | } |
---|
37 | |
---|
38 | |
---|
39 | /* cmu_bdd_new_assoc(bddm, assoc_info, pairs) creates or finds a variable */ |
---|
40 | /* association given by assoc_info. pairs is 0 if the information */ |
---|
41 | /* represents only a list of variables rather than a full association. */ |
---|
42 | |
---|
43 | int |
---|
44 | cmu_bdd_new_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs) |
---|
45 | { |
---|
46 | long i; |
---|
47 | assoc_list p, *q; |
---|
48 | bdd f; |
---|
49 | bdd *assoc; |
---|
50 | bdd_indexindex_type j; |
---|
51 | long last; |
---|
52 | |
---|
53 | if (!check_assoc(bddm, assoc_info, pairs)) |
---|
54 | return (-1); |
---|
55 | assoc=(bdd *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(bdd))); |
---|
56 | /* Unpack the association. */ |
---|
57 | for (i=0; i < bddm->maxvars; ++i) |
---|
58 | assoc[i+1]=0; |
---|
59 | if (pairs) |
---|
60 | for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2) |
---|
61 | { |
---|
62 | BDD_SETUP(f); |
---|
63 | assoc[BDD_INDEXINDEX(f)]=assoc_info[i+1]; |
---|
64 | } |
---|
65 | else |
---|
66 | for (i=0; (f=assoc_info[i]); ++i) |
---|
67 | { |
---|
68 | BDD_SETUP(f); |
---|
69 | assoc[BDD_INDEXINDEX(f)]=BDD_ONE(bddm); |
---|
70 | } |
---|
71 | /* Check for existence. */ |
---|
72 | for (p=bddm->assocs; p; p=p->next) |
---|
73 | if (cmu_bdd_assoc_eq(bddm, p->va.assoc, assoc)) |
---|
74 | { |
---|
75 | mem_free_block((pointer)assoc); |
---|
76 | p->refs++; |
---|
77 | return (p->id); |
---|
78 | } |
---|
79 | /* Find the first unused id. */ |
---|
80 | for (q= &bddm->assocs, p= *q, i=0; p && p->id == i; q= &p->next, p= *q, ++i); |
---|
81 | p=(assoc_list)BDD_NEW_REC(bddm, sizeof(struct assoc_list_)); |
---|
82 | p->id=i; |
---|
83 | p->next= *q; |
---|
84 | *q=p; |
---|
85 | p->va.assoc=assoc; |
---|
86 | last= -1; |
---|
87 | if (pairs) |
---|
88 | for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2) |
---|
89 | { |
---|
90 | BDD_SETUP(f); |
---|
91 | j=BDD_INDEXINDEX(f); |
---|
92 | if ((long)bddm->indexes[j] > last) |
---|
93 | last=bddm->indexes[j]; |
---|
94 | } |
---|
95 | else |
---|
96 | for (i=0; (f=assoc_info[i]); ++i) |
---|
97 | { |
---|
98 | BDD_SETUP(f); |
---|
99 | j=BDD_INDEXINDEX(f); |
---|
100 | if ((long)bddm->indexes[j] > last) |
---|
101 | last=bddm->indexes[j]; |
---|
102 | } |
---|
103 | p->va.last=last; |
---|
104 | p->refs=1; |
---|
105 | /* Protect BDDs in the association. */ |
---|
106 | if (pairs) |
---|
107 | for (i=0; assoc_info[i] && (f=assoc_info[i+1]); i+=2) |
---|
108 | { |
---|
109 | BDD_SETUP(f); |
---|
110 | BDD_INCREFS(f); |
---|
111 | } |
---|
112 | return (p->id); |
---|
113 | } |
---|
114 | |
---|
115 | |
---|
116 | static |
---|
117 | int |
---|
118 | bdd_flush_id_entries(cmu_bdd_manager bddm, cache_entry p, pointer closure) |
---|
119 | { |
---|
120 | int (*flush_fn)(cmu_bdd_manager, cache_entry, pointer); |
---|
121 | |
---|
122 | flush_fn=bddm->op_cache.flush_fn[TAG(p)]; |
---|
123 | if (flush_fn) |
---|
124 | return ((*flush_fn)(bddm, CACHE_POINTER(p), closure)); |
---|
125 | return (0); |
---|
126 | } |
---|
127 | |
---|
128 | |
---|
129 | /* cmu_bdd_free_assoc(bddm, id) deletes the variable association given by */ |
---|
130 | /* id. */ |
---|
131 | |
---|
132 | void |
---|
133 | cmu_bdd_free_assoc(cmu_bdd_manager bddm, int assoc_id) |
---|
134 | { |
---|
135 | bdd_indexindex_type i; |
---|
136 | bdd f; |
---|
137 | assoc_list p, *q; |
---|
138 | |
---|
139 | if (bddm->curr_assoc_id == assoc_id) |
---|
140 | { |
---|
141 | bddm->curr_assoc_id= -1; |
---|
142 | bddm->curr_assoc= &bddm->temp_assoc; |
---|
143 | } |
---|
144 | for (q= &bddm->assocs, p= *q; p; q= &p->next, p= *q) |
---|
145 | if (p->id == assoc_id) |
---|
146 | { |
---|
147 | p->refs--; |
---|
148 | if (!p->refs) |
---|
149 | { |
---|
150 | /* Unprotect the BDDs in the association. */ |
---|
151 | for (i=0; i < bddm->vars; ++i) |
---|
152 | if ((f=p->va.assoc[i+1])) |
---|
153 | { |
---|
154 | BDD_SETUP(f); |
---|
155 | BDD_DECREFS(f); |
---|
156 | } |
---|
157 | /* Flush old cache entries. */ |
---|
158 | bdd_flush_cache(bddm, bdd_flush_id_entries, (pointer)((long)assoc_id)); |
---|
159 | *q=p->next; |
---|
160 | mem_free_block((pointer)(p->va.assoc)); |
---|
161 | BDD_FREE_REC(bddm, (pointer)p, sizeof(struct assoc_list_)); |
---|
162 | } |
---|
163 | return; |
---|
164 | } |
---|
165 | cmu_bdd_warning("cmu_bdd_free_assoc: no variable association with specified ID"); |
---|
166 | } |
---|
167 | |
---|
168 | |
---|
169 | /* cmu_bdd_augment_temp_assoc(bddm, assoc_info, pairs) adds to the temporary */ |
---|
170 | /* variable association as specified by assoc_info. pairs is 0 if the */ |
---|
171 | /* information represents only a list of variables rather than a full */ |
---|
172 | /* association. */ |
---|
173 | |
---|
174 | void |
---|
175 | cmu_bdd_augment_temp_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs) |
---|
176 | { |
---|
177 | long i; |
---|
178 | bdd_indexindex_type j; |
---|
179 | bdd f; |
---|
180 | long last; |
---|
181 | |
---|
182 | if (check_assoc(bddm, assoc_info, pairs)) |
---|
183 | { |
---|
184 | last=bddm->temp_assoc.last; |
---|
185 | if (pairs) |
---|
186 | for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2) |
---|
187 | { |
---|
188 | BDD_SETUP(f); |
---|
189 | j=BDD_INDEXINDEX(f); |
---|
190 | if ((long)bddm->indexes[j] > last) |
---|
191 | last=bddm->indexes[j]; |
---|
192 | if ((f=bddm->temp_assoc.assoc[j])) |
---|
193 | { |
---|
194 | BDD_SETUP(f); |
---|
195 | BDD_DECREFS(f); |
---|
196 | } |
---|
197 | f=assoc_info[i+1]; |
---|
198 | BDD_RESET(f); |
---|
199 | bddm->temp_assoc.assoc[j]=f; |
---|
200 | /* Protect BDDs in the association. */ |
---|
201 | BDD_INCREFS(f); |
---|
202 | } |
---|
203 | else |
---|
204 | for (i=0; (f=assoc_info[i]); ++i) |
---|
205 | { |
---|
206 | BDD_SETUP(f); |
---|
207 | j=BDD_INDEXINDEX(f); |
---|
208 | if ((long)bddm->indexes[j] > last) |
---|
209 | last=bddm->indexes[j]; |
---|
210 | if ((f=bddm->temp_assoc.assoc[j])) |
---|
211 | { |
---|
212 | BDD_SETUP(f); |
---|
213 | BDD_DECREFS(f); |
---|
214 | } |
---|
215 | bddm->temp_assoc.assoc[j]=BDD_ONE(bddm); |
---|
216 | } |
---|
217 | bddm->temp_assoc.last=last; |
---|
218 | } |
---|
219 | } |
---|
220 | |
---|
221 | |
---|
222 | /* cmu_bdd_temp_assoc(bddm, assoc_info, pairs) sets the temporary variable */ |
---|
223 | /* association as specified by assoc_info. pairs is 0 if the */ |
---|
224 | /* information represents only a list of variables rather than a full */ |
---|
225 | /* association. */ |
---|
226 | |
---|
227 | void |
---|
228 | cmu_bdd_temp_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs) |
---|
229 | { |
---|
230 | long i; |
---|
231 | bdd f; |
---|
232 | |
---|
233 | /* Clean up old temporary association. */ |
---|
234 | for (i=0; i < bddm->vars; ++i) |
---|
235 | { |
---|
236 | if ((f=bddm->temp_assoc.assoc[i+1])) |
---|
237 | { |
---|
238 | BDD_SETUP(f); |
---|
239 | BDD_DECREFS(f); |
---|
240 | } |
---|
241 | bddm->temp_assoc.assoc[i+1]=0; |
---|
242 | } |
---|
243 | bddm->temp_assoc.last= -1; |
---|
244 | cmu_bdd_augment_temp_assoc(bddm, assoc_info, pairs); |
---|
245 | } |
---|
246 | |
---|
247 | |
---|
248 | /* cmu_bdd_assoc(bddm, id) sets the current variable association to the */ |
---|
249 | /* one given by id and returns the ID of the old association. An */ |
---|
250 | /* id of -1 indicates the temporary association. */ |
---|
251 | |
---|
252 | int |
---|
253 | cmu_bdd_assoc(cmu_bdd_manager bddm, int assoc_id) |
---|
254 | { |
---|
255 | int old_assoc; |
---|
256 | assoc_list p; |
---|
257 | |
---|
258 | old_assoc=bddm->curr_assoc_id; |
---|
259 | if (assoc_id != -1) |
---|
260 | { |
---|
261 | for (p=bddm->assocs; p; p=p->next) |
---|
262 | if (p->id == assoc_id) |
---|
263 | { |
---|
264 | bddm->curr_assoc_id=p->id; |
---|
265 | bddm->curr_assoc= &p->va; |
---|
266 | return (old_assoc); |
---|
267 | } |
---|
268 | cmu_bdd_warning("cmu_bdd_assoc: no variable association with specified ID"); |
---|
269 | } |
---|
270 | bddm->curr_assoc_id= -1; |
---|
271 | bddm->curr_assoc= &bddm->temp_assoc; |
---|
272 | return (old_assoc); |
---|
273 | } |
---|