00001
00002
00003
00004 #include "bddint.h"
00005
00006
00007 #define MIN_GC_LIMIT 10000
00008
00009
00010 void
00011 bdd_rehash_var_table(var_table table, int grow)
00012 {
00013 long i;
00014 long hash;
00015 long oldsize;
00016 bdd *newtable;
00017 bdd p, q;
00018
00019 oldsize=table->size;
00020 if (grow)
00021 table->size_index++;
00022 else
00023 table->size_index--;
00024 table->size=TABLE_SIZE(table->size_index);
00025 newtable=(bdd *)mem_get_block((SIZE_T)(table->size*sizeof(bdd)));
00026 for (i=0; i < table->size; ++i)
00027 newtable[i]=0;
00028 for (i=0; i < oldsize; ++i)
00029 for (p=table->table[i]; p; p=q)
00030 {
00031 q=p->next;
00032 hash=HASH_NODE(p->data[0], p->data[1]);
00033 BDD_REDUCE(hash, table->size);
00034 p->next=newtable[hash];
00035 newtable[hash]=p;
00036 }
00037 mem_free_block((pointer)table->table);
00038 table->table=newtable;
00039 }
00040
00041
00042 static
00043 void
00044 bdd_mark(cmu_bdd_manager bddm)
00045 {
00046 long i, j;
00047 var_table table;
00048 bdd f, g;
00049
00050 for (i=0; i <= bddm->vars; ++i)
00051 {
00052 if (i == bddm->vars)
00053 table=bddm->unique_table.tables[BDD_CONST_INDEXINDEX];
00054 else
00055 table=bddm->unique_table.tables[bddm->indexindexes[i]];
00056 for (j=0; j < table->size; ++j)
00057 for (f=table->table[j]; f; f=f->next)
00058 {
00059 BDD_SETUP(f);
00060 if (BDD_REFS(f) || BDD_TEMP_REFS(f))
00061 BDD_MARK(f)|=BDD_GC_MARK;
00062 if (BDD_IS_USED(f) && !BDD_IS_CONST(f))
00063 {
00064 g=(bdd)BDD_DATA0(f);
00065 {
00066 BDD_SETUP(g);
00067 BDD_MARK(g)|=BDD_GC_MARK;
00068 }
00069 g=(bdd)BDD_DATA1(f);
00070 {
00071 BDD_SETUP(g);
00072 BDD_MARK(g)|=BDD_GC_MARK;
00073 }
00074 }
00075 }
00076 }
00077 }
00078
00079
00080 void
00081 bdd_sweep_var_table(cmu_bdd_manager bddm, long i, int maybe_rehash)
00082 {
00083 long j;
00084 var_table table;
00085 bdd f, *p;
00086
00087 table=bddm->unique_table.tables[i];
00088 for (j=0; j < table->size; ++j)
00089 for (p= &table->table[j], f= *p; f; f= *p)
00090 {
00091 BDD_SETUP(f);
00092 if (BDD_IS_USED(f))
00093 {
00094 BDD_SETUP(f);
00095 BDD_MARK(f)&=~BDD_GC_MARK;
00096 p= &f->next;
00097 }
00098 else
00099 {
00100 *p=f->next;
00101 if (i == BDD_CONST_INDEXINDEX && bddm->unique_table.free_terminal_fn)
00102 (*bddm->unique_table.free_terminal_fn)(bddm,
00103 BDD_DATA0(f),
00104 BDD_DATA1(f),
00105 bddm->unique_table.free_terminal_env);
00106 BDD_FREE_REC(bddm, (pointer)f, sizeof(struct bdd_));
00107 table->entries--;
00108 bddm->unique_table.entries--;
00109 bddm->unique_table.freed++;
00110 }
00111 }
00112 if (maybe_rehash && table->size > table->entries && table->size_index > 3)
00113 bdd_rehash_var_table(table, 0);
00114 }
00115
00116
00117 void
00118 bdd_sweep(cmu_bdd_manager bddm)
00119 {
00120 long i;
00121
00122 for (i=0; i <= bddm->vars; ++i)
00123 bdd_sweep_var_table(bddm, i, 1);
00124 }
00125
00126
00127
00128
00129 void
00130 cmu_bdd_gc(cmu_bdd_manager bddm)
00131 {
00132 bdd_mark(bddm);
00133 bdd_purge_cache(bddm);
00134 bdd_sweep(bddm);
00135 bddm->unique_table.gcs++;
00136 }
00137
00138
00139 static
00140 void
00141 bdd_set_gc_limit(cmu_bdd_manager bddm)
00142 {
00143 bddm->unique_table.gc_limit=2*bddm->unique_table.entries;
00144 if (bddm->unique_table.gc_limit < MIN_GC_LIMIT)
00145 bddm->unique_table.gc_limit=MIN_GC_LIMIT;
00146 if (bddm->unique_table.node_limit &&
00147 bddm->unique_table.gc_limit > bddm->unique_table.node_limit)
00148 bddm->unique_table.gc_limit=bddm->unique_table.node_limit;
00149 }
00150
00151
00152 void
00153 bdd_clear_temps(cmu_bdd_manager bddm)
00154 {
00155 long i, j;
00156 var_table table;
00157 bdd f;
00158
00159 for (i=0; i <= bddm->vars; ++i)
00160 {
00161 table=bddm->unique_table.tables[i];
00162 for (j=0; j < table->size; ++j)
00163 for (f=table->table[j]; f; f=f->next)
00164 {
00165 BDD_SETUP(f);
00166 BDD_TEMP_REFS(f)=0;
00167 }
00168 }
00169 cmu_bdd_gc(bddm);
00170 bdd_set_gc_limit(bddm);
00171 }
00172
00173
00174 void
00175 bdd_cleanup(cmu_bdd_manager bddm, int code)
00176 {
00177 bdd_clear_temps(bddm);
00178 switch (code)
00179 {
00180 case BDD_ABORTED:
00181 (*bddm->bag_it_fn)(bddm, bddm->bag_it_env);
00182 break;
00183 case BDD_OVERFLOWED:
00184 if (bddm->overflow_fn)
00185 (*bddm->overflow_fn)(bddm, bddm->overflow_env);
00186 break;
00187 }
00188 }
00189
00190
00191 bdd
00192 bdd_find_aux(cmu_bdd_manager bddm, bdd_indexindex_type indexindex, INT_PTR d1, INT_PTR d2)
00193 {
00194 var_table table;
00195 long hash;
00196 bdd temp;
00197
00198 table=bddm->unique_table.tables[indexindex];
00199 hash=HASH_NODE(d1, d2);
00200 BDD_REDUCE(hash, table->size);
00201 for (temp=table->table[hash]; temp; temp=temp->next)
00202 if (temp->data[0] == d1 && temp->data[1] == d2)
00203 break;
00204 if (!temp)
00205 {
00206
00207 temp=(bdd)BDD_NEW_REC(bddm, sizeof(struct bdd_));
00208 temp->indexindex=indexindex;
00209 temp->refs=0;
00210 temp->mark=0;
00211 temp->data[0]=d1;
00212 temp->data[1]=d2;
00213 temp->next=table->table[hash];
00214 table->table[hash]=temp;
00215 table->entries++;
00216 bddm->unique_table.entries++;
00217 if (4*table->size < table->entries)
00218 bdd_rehash_var_table(table, 1);
00219 }
00220 bddm->unique_table.finds++;
00221 return (temp);
00222 }
00223
00224
00225 static
00226 void
00227 bdd_check(cmu_bdd_manager bddm)
00228 {
00229 long nodes;
00230
00231 bddm->check=100;
00232
00233 if (bddm->bag_it_fn)
00234 longjmp(bddm->abort.context, BDD_ABORTED);
00235 if (bddm->unique_table.entries > bddm->unique_table.gc_limit)
00236 {
00237 cmu_bdd_gc(bddm);
00238
00239 nodes=bddm->unique_table.entries;
00240 if (3*nodes > 2*bddm->unique_table.gc_limit && bddm->allow_reordering && bddm->reorder_fn)
00241 {
00242 cmu_bdd_reorder_aux(bddm);
00243 if (4*bddm->unique_table.entries > 3*nodes && 3*nodes > 4*bddm->nodes_at_start)
00244
00245
00246 bddm->allow_reordering=0;
00247
00248 bdd_set_gc_limit(bddm);
00249 longjmp(bddm->abort.context, BDD_REORDERED);
00250 }
00251 bdd_set_gc_limit(bddm);
00252 if (bddm->unique_table.node_limit &&
00253 bddm->unique_table.entries >= bddm->unique_table.node_limit-1000)
00254 {
00255
00256 bddm->overflow=1;
00257 longjmp(bddm->abort.context, BDD_OVERFLOWED);
00258 }
00259 }
00260
00261 if (3*bddm->op_cache.size < 2*bddm->op_cache.entries &&
00262 32*bddm->op_cache.size < bddm->op_cache.cache_ratio*bddm->unique_table.entries)
00263 bdd_rehash_cache(bddm, 1);
00264 }
00265
00266
00267
00268
00269
00270 bdd
00271 bdd_find(cmu_bdd_manager bddm, bdd_indexindex_type indexindex, bdd f, bdd g)
00272 {
00273 bdd temp;
00274
00275 BDD_SETUP(f);
00276 BDD_SETUP(g);
00277 if (f == g)
00278 {
00279 BDD_TEMP_DECREFS(f);
00280 temp=f;
00281 }
00282 else
00283 {
00284 if (BDD_IS_OUTPOS(f))
00285 temp=bdd_find_aux(bddm, indexindex, (INT_PTR)f, (INT_PTR)g);
00286 else
00287 temp=BDD_NOT(bdd_find_aux(bddm, indexindex, (INT_PTR)BDD_NOT(f), (INT_PTR)BDD_NOT(g)));
00288 {
00289 BDD_SETUP(temp);
00290 BDD_TEMP_INCREFS(temp);
00291 }
00292 BDD_TEMP_DECREFS(f);
00293 BDD_TEMP_DECREFS(g);
00294 }
00295 bddm->check--;
00296 if (!bddm->check)
00297 bdd_check(bddm);
00298 return (temp);
00299 }
00300
00301
00302
00303
00304
00305 bdd
00306 bdd_find_terminal(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2)
00307 {
00308 bdd temp;
00309
00310 if ((*bddm->canonical_fn)(bddm, value1, value2, bddm->transform_env))
00311 {
00312 (*bddm->transform_fn)(bddm, value1, value2, &value1, &value2, bddm->transform_env);
00313 temp=BDD_NOT(bdd_find_aux(bddm, BDD_CONST_INDEXINDEX, value1, value2));
00314 }
00315 else
00316 temp=bdd_find_aux(bddm, BDD_CONST_INDEXINDEX, value1, value2);
00317 {
00318 BDD_SETUP(temp);
00319 BDD_TEMP_INCREFS(temp);
00320 }
00321 bddm->check--;
00322 if (!bddm->check)
00323 bdd_check(bddm);
00324 return (temp);
00325 }
00326
00327
00328
00329
00330 void
00331 cmu_bdd_clear_refs(cmu_bdd_manager bddm)
00332 {
00333 long i, j;
00334 var_table table;
00335 bdd f;
00336 assoc_list q;
00337
00338 for (i=0; i <= bddm->vars; ++i)
00339 {
00340 table=bddm->unique_table.tables[i];
00341 for (j=0; j < table->size; ++j)
00342 for (f=table->table[j]; f; f=f->next)
00343 {
00344 BDD_SETUP(f);
00345 BDD_REFS(f)=0;
00346 }
00347 }
00348 for (i=0; i < bddm->vars; ++i)
00349 bddm->variables[i+1]->refs=BDD_MAX_REFS;
00350 bddm->one->refs=BDD_MAX_REFS;
00351 for (q=bddm->assocs; q; q=q->next)
00352 for (i=0; i < bddm->vars; ++i)
00353 if ((f=q->va.assoc[i+1]))
00354 {
00355 BDD_SETUP(f);
00356 BDD_INCREFS(f);
00357 }
00358 }
00359
00360
00361 var_table
00362 bdd_new_var_table(cmu_bdd_manager bddm)
00363 {
00364 long i;
00365 var_table table;
00366
00367 table=(var_table)BDD_NEW_REC(bddm, sizeof(struct var_table_));
00368 table->size_index=3;
00369 table->size=TABLE_SIZE(table->size_index);
00370 table->entries=0;
00371 table->table=(bdd *)mem_get_block((SIZE_T)(table->size*sizeof(bdd)));
00372 for (i=0; i < table->size; ++i)
00373 table->table[i]=0;
00374 return (table);
00375 }
00376
00377
00378 void
00379 cmu_bdd_init_unique(cmu_bdd_manager bddm)
00380 {
00381 bddm->unique_table.tables=(var_table *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(var_table)));
00382 bddm->unique_table.tables[BDD_CONST_INDEXINDEX]=bdd_new_var_table(bddm);
00383 bddm->unique_table.gc_limit=MIN_GC_LIMIT;
00384 bddm->unique_table.node_limit=0;
00385 bddm->unique_table.entries=0;
00386 bddm->unique_table.freed=0;
00387 bddm->unique_table.gcs=0;
00388 bddm->unique_table.finds=0;
00389 bddm->unique_table.free_terminal_fn=0;
00390 bddm->unique_table.free_terminal_env=0;
00391 }
00392
00393
00394 void
00395 cmu_bdd_free_unique(cmu_bdd_manager bddm)
00396 {
00397 long i, j;
00398 var_table table;
00399 bdd p, q;
00400
00401 for (i=0; i <= bddm->vars; ++i)
00402 {
00403 table=bddm->unique_table.tables[i];
00404 for (j=0; j < table->size; ++j)
00405 for (p=table->table[j]; p; p=q)
00406 {
00407 q=p->next;
00408 BDD_FREE_REC(bddm, (pointer)p, sizeof(struct bdd_));
00409 }
00410 mem_free_block((pointer)table->table);
00411 BDD_FREE_REC(bddm, (pointer)table, sizeof(struct var_table_));
00412 }
00413 mem_free_block((pointer)bddm->unique_table.tables);
00414 }