nysol-zdd 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/zdd_so/BDD.cc +495 -0
- data/ext/zdd_so/BDD.h +356 -0
- data/ext/zdd_so/BDDDG.cc +1818 -0
- data/ext/zdd_so/BDDDG.h +107 -0
- data/ext/zdd_so/BDDHASH.cc +91 -0
- data/ext/zdd_so/BtoI.cc +503 -0
- data/ext/zdd_so/BtoI.h +144 -0
- data/ext/zdd_so/CtoI.cc +1072 -0
- data/ext/zdd_so/CtoI.h +186 -0
- data/ext/zdd_so/MLZBDDV.cc +153 -0
- data/ext/zdd_so/MLZBDDV.h +42 -0
- data/ext/zdd_so/SOP.cc +608 -0
- data/ext/zdd_so/SOP.h +199 -0
- data/ext/zdd_so/ZBDD.cc +1035 -0
- data/ext/zdd_so/ZBDD.h +243 -0
- data/ext/zdd_so/ZBDDDG.cc +1834 -0
- data/ext/zdd_so/ZBDDDG.h +105 -0
- data/ext/zdd_so/ZBDDHASH.cc +91 -0
- data/ext/zdd_so/bddc.c +2816 -0
- data/ext/zdd_so/bddc.h +132 -0
- data/ext/zdd_so/extconf.rb +25 -0
- data/ext/zdd_so/include/aheap.c +211 -0
- data/ext/zdd_so/include/aheap.h +111 -0
- data/ext/zdd_so/include/base.c +93 -0
- data/ext/zdd_so/include/base.h +60 -0
- data/ext/zdd_so/include/itemset.c +473 -0
- data/ext/zdd_so/include/itemset.h +153 -0
- data/ext/zdd_so/include/problem.c +371 -0
- data/ext/zdd_so/include/problem.h +160 -0
- data/ext/zdd_so/include/queue.c +518 -0
- data/ext/zdd_so/include/queue.h +177 -0
- data/ext/zdd_so/include/sgraph.c +331 -0
- data/ext/zdd_so/include/sgraph.h +170 -0
- data/ext/zdd_so/include/stdlib2.c +832 -0
- data/ext/zdd_so/include/stdlib2.h +746 -0
- data/ext/zdd_so/include/trsact.c +723 -0
- data/ext/zdd_so/include/trsact.h +167 -0
- data/ext/zdd_so/include/vec.c +583 -0
- data/ext/zdd_so/include/vec.h +159 -0
- data/ext/zdd_so/lcm-vsop.cc +596 -0
- data/ext/zdd_so/print.cc +683 -0
- data/ext/zdd_so/table.cc +330 -0
- data/ext/zdd_so/vsop.h +88 -0
- data/ext/zdd_so/zdd_so.cpp +3277 -0
- data/lib/nysol/zdd.rb +31 -0
- metadata +131 -0
data/ext/zdd_so/ZBDDDG.h
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
/*****************************************
|
2
|
+
* ZZBDDDG - Decomposition Graph *
|
3
|
+
* (SAPPORO-1.02) - Header *
|
4
|
+
* (C) Shin-ichi MINATO (Aug. 8, 2005) *
|
5
|
+
*****************************************/
|
6
|
+
|
7
|
+
#ifndef _ZBDDDG_
|
8
|
+
#define _ZBDDDG_
|
9
|
+
|
10
|
+
#include "ZBDD.h"
|
11
|
+
|
12
|
+
#define ZBDDDG_InitSize 4
|
13
|
+
|
14
|
+
#define ZBDDDG_NIL BDD_MaxNode
|
15
|
+
|
16
|
+
#define ZBDDDG_C0 1
|
17
|
+
#define ZBDDDG_P1 2
|
18
|
+
#define ZBDDDG_LIT 3
|
19
|
+
#define ZBDDDG_AND 4
|
20
|
+
#define ZBDDDG_OR 5
|
21
|
+
#define ZBDDDG_OTHER 6
|
22
|
+
|
23
|
+
class ZBDDDG
|
24
|
+
{
|
25
|
+
struct Node;
|
26
|
+
struct NodeLink
|
27
|
+
{
|
28
|
+
bddword _ndx;
|
29
|
+
bddword _nxt;
|
30
|
+
NodeLink(void){ _ndx = ZBDDDG_NIL; _nxt = ZBDDDG_NIL; }
|
31
|
+
};
|
32
|
+
|
33
|
+
bddword _nodeSize;
|
34
|
+
bddword _nodeUsed;
|
35
|
+
bddword _linkSize;
|
36
|
+
bddword _linkUsed;
|
37
|
+
bddword* _hashWheel;
|
38
|
+
Node* _nodeA;
|
39
|
+
NodeLink* _linkA;
|
40
|
+
bddword _c0;
|
41
|
+
bddword _c1;
|
42
|
+
|
43
|
+
bddword HashIndex(ZBDD);
|
44
|
+
bddword NewNdx(ZBDD, char);
|
45
|
+
int EnlargeNode(void);
|
46
|
+
bddword NewLkx(bddword);
|
47
|
+
int EnlargeLink(void);
|
48
|
+
int LinkNodes(bddword, bddword);
|
49
|
+
int Merge3(bddword, bddword, bddword);
|
50
|
+
ZBDD Func0(ZBDD, ZBDD);
|
51
|
+
ZBDD Func1(ZBDD, ZBDD);
|
52
|
+
int LinkNodesC3(bddword, bddword);
|
53
|
+
void Print0(bddword);
|
54
|
+
bddword Merge(ZBDD, bddword, bddword);
|
55
|
+
bddword ReferNdx(ZBDD);
|
56
|
+
int PhaseSweep(bddword);
|
57
|
+
void MarkSweep(bddword);
|
58
|
+
void MarkSweepR(bddword);
|
59
|
+
int Mark1(bddword);
|
60
|
+
void Mark2R(bddword);
|
61
|
+
int MarkChkR(bddword);
|
62
|
+
void Mark3R(bddword);
|
63
|
+
bddword Mark4R(bddword, bddword, bddword);
|
64
|
+
bddword Mark5R(bddword, bddword, bddword);
|
65
|
+
void Mark6R(bddword, bddword);
|
66
|
+
bddword AppendR(bddword, int, bddword, bddword);
|
67
|
+
|
68
|
+
struct Node
|
69
|
+
{
|
70
|
+
bddword _lkx;
|
71
|
+
ZBDD _f;
|
72
|
+
bddword _ndxP;
|
73
|
+
char _type; // NULL, C1, P1, LIT, OR, XOR, OTHER
|
74
|
+
char _mark;
|
75
|
+
Node(void);
|
76
|
+
Node(ZBDD, char);
|
77
|
+
};
|
78
|
+
|
79
|
+
public:
|
80
|
+
ZBDDDG(void);
|
81
|
+
~ZBDDDG(void);
|
82
|
+
void Clear(void);
|
83
|
+
bddword NodeUsed(void);
|
84
|
+
int PrintDecomp(ZBDD);
|
85
|
+
bddword Decomp(ZBDD);
|
86
|
+
|
87
|
+
friend class ZBDDDG_Tag;
|
88
|
+
};
|
89
|
+
|
90
|
+
class ZBDDDG_Tag
|
91
|
+
{
|
92
|
+
ZBDDDG* _dg;
|
93
|
+
bddword _ndx;
|
94
|
+
bddword _lkx;
|
95
|
+
public:
|
96
|
+
ZBDDDG_Tag(void);
|
97
|
+
int Set(ZBDDDG *, bddword);
|
98
|
+
bddword TopNdx(void);
|
99
|
+
bddword NextNdx(void);
|
100
|
+
char Type(void);
|
101
|
+
ZBDD Func(void);
|
102
|
+
};
|
103
|
+
|
104
|
+
#endif // _ZBDDDG_
|
105
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
/****************************************
|
2
|
+
* ZBDD+ Manipulator (SAPPORO-1.59) *
|
3
|
+
* (Hash table methods) *
|
4
|
+
* (C) Shin-ichi MINATO (Dec. 10, 2013) *
|
5
|
+
****************************************/
|
6
|
+
|
7
|
+
#include "ZBDD.h"
|
8
|
+
|
9
|
+
using std::cerr;
|
10
|
+
|
11
|
+
ZBDD_Hash::ZBDD_Hash()
|
12
|
+
{
|
13
|
+
_hashSize = 16;
|
14
|
+
_wheel = new ZBDD_Entry[_hashSize];
|
15
|
+
_amount = 0;
|
16
|
+
}
|
17
|
+
|
18
|
+
ZBDD_Hash::~ZBDD_Hash() { delete[] _wheel; }
|
19
|
+
|
20
|
+
void ZBDD_Hash::Clear()
|
21
|
+
{
|
22
|
+
if(_hashSize != 0) delete[] _wheel;
|
23
|
+
_hashSize = 16;
|
24
|
+
_wheel = new ZBDD_Entry[_hashSize];
|
25
|
+
_amount = 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
ZBDD_Hash::ZBDD_Entry* ZBDD_Hash::GetEntry(ZBDD key)
|
29
|
+
{
|
30
|
+
bddword id = key.GetID();
|
31
|
+
bddword hash = (id+(id>>10)+(id>>20)) & (_hashSize - 1);
|
32
|
+
bddword i = hash;
|
33
|
+
while(_wheel[i]._key != -1)
|
34
|
+
{
|
35
|
+
if(key == _wheel[i]._key) return & _wheel[i];
|
36
|
+
i++;
|
37
|
+
i &= (_hashSize -1);
|
38
|
+
}
|
39
|
+
i = hash;
|
40
|
+
while(_wheel[i]._key != -1)
|
41
|
+
{
|
42
|
+
if(_wheel[i]._ptr == 0) break;
|
43
|
+
i++;
|
44
|
+
i &= (_hashSize -1);
|
45
|
+
}
|
46
|
+
return & _wheel[i];
|
47
|
+
}
|
48
|
+
|
49
|
+
void ZBDD_Hash::Enlarge()
|
50
|
+
{
|
51
|
+
bddword oldSize = _hashSize;
|
52
|
+
ZBDD_Entry* oldWheel = _wheel;
|
53
|
+
|
54
|
+
_hashSize <<= 2;
|
55
|
+
_wheel = new ZBDD_Entry[_hashSize];
|
56
|
+
if(_wheel == 0)
|
57
|
+
{
|
58
|
+
cerr << "<ERROR> ZBDD_Hash::Enlarge(): Memory overflow (";
|
59
|
+
cerr << _hashSize << ")\n";
|
60
|
+
exit(1);
|
61
|
+
}
|
62
|
+
_amount = 0;
|
63
|
+
for(bddword i=0; i<oldSize; i++)
|
64
|
+
if(oldWheel[i]._ptr != 0)
|
65
|
+
if(oldWheel[i]._key != -1)
|
66
|
+
Enter(oldWheel[i]._key, oldWheel[i]._ptr);
|
67
|
+
delete[] oldWheel;
|
68
|
+
}
|
69
|
+
|
70
|
+
void ZBDD_Hash::Enter(ZBDD key, void* ptr)
|
71
|
+
// ptr = 0 means deleting.
|
72
|
+
{
|
73
|
+
ZBDD_Entry* ent = GetEntry(key);
|
74
|
+
if(ent -> _key == -1) _amount++;
|
75
|
+
else if(ent -> _ptr == 0) _amount++;
|
76
|
+
if(ptr == 0) _amount--;
|
77
|
+
ent -> _key = key;
|
78
|
+
ent -> _ptr = ptr;
|
79
|
+
if(_amount >= (_hashSize>>1)) Enlarge();
|
80
|
+
}
|
81
|
+
|
82
|
+
void* ZBDD_Hash::Refer(ZBDD key)
|
83
|
+
// returns 0 if not found.
|
84
|
+
{
|
85
|
+
ZBDD_Entry* ent = GetEntry(key);
|
86
|
+
if(ent -> _key == -1) return 0;
|
87
|
+
return ent -> _ptr;
|
88
|
+
}
|
89
|
+
|
90
|
+
bddword ZBDD_Hash::Amount() { return _amount; }
|
91
|
+
|
data/ext/zdd_so/bddc.c
ADDED
@@ -0,0 +1,2816 @@
|
|
1
|
+
/*****************************************
|
2
|
+
* BDD Package (SAPPORO-1.70) - Body *
|
3
|
+
* (C) Shin-ichi MINATO (Sep. 16, 2015) *
|
4
|
+
******************************************/
|
5
|
+
|
6
|
+
#include <stdio.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include "bddc.h"
|
9
|
+
|
10
|
+
/* ----------------- MACRO Definitions ---------------- */
|
11
|
+
/* Operation IDs in Cache */
|
12
|
+
#define BC_NULL 0
|
13
|
+
#define BC_AND 1
|
14
|
+
#define BC_XOR 2
|
15
|
+
#define BC_AT0 3
|
16
|
+
#define BC_AT1 4
|
17
|
+
#define BC_LSHIFT 5
|
18
|
+
#define BC_RSHIFT 6
|
19
|
+
#define BC_COFACTOR 7
|
20
|
+
#define BC_UNIV 8
|
21
|
+
#define BC_SUPPORT 9
|
22
|
+
#define BC_INTERSEC 10
|
23
|
+
#define BC_UNION 11
|
24
|
+
#define BC_SUBTRACT 12
|
25
|
+
#define BC_OFFSET 13
|
26
|
+
#define BC_ONSET 14
|
27
|
+
#define BC_CHANGE 15
|
28
|
+
#define BC_CARD 16
|
29
|
+
#define BC_LIT 17
|
30
|
+
#define BC_LEN 18
|
31
|
+
|
32
|
+
/* Macros for malloc, realloc */
|
33
|
+
#define B_MALLOC(type, size) \
|
34
|
+
(type *)malloc(sizeof(type) * size)
|
35
|
+
#define B_REALLOC(ptr, type, size) \
|
36
|
+
(type *)realloc(ptr, sizeof(type) * size)
|
37
|
+
|
38
|
+
/* Printf format of bddp */
|
39
|
+
#ifdef B_64
|
40
|
+
# define B_BDDP_FD "%lld"
|
41
|
+
# define B_BDDP_FX "0x%llX"
|
42
|
+
#else
|
43
|
+
# define B_BDDP_FD "%d"
|
44
|
+
# define B_BDDP_FX "0x%X"
|
45
|
+
#endif
|
46
|
+
|
47
|
+
/* strtol or strtoll */
|
48
|
+
#ifdef B_64
|
49
|
+
# define B_STRTOI strtoll
|
50
|
+
#else
|
51
|
+
# define B_STRTOI strtol
|
52
|
+
#endif
|
53
|
+
|
54
|
+
/* Table spaces */
|
55
|
+
#define B_NODE_MAX (B_VAL_MASK>>1U) /* Max number of BDD nodes */
|
56
|
+
#define B_NODE_SPC0 256 /* Default initial node size */
|
57
|
+
#define B_VAR_SPC0 16 /* Initial var table size */
|
58
|
+
#define B_HASH_SPC0 4 /* Initial hash size */
|
59
|
+
#define B_RFCT_SPC0 4 /* Initial RFCT size */
|
60
|
+
|
61
|
+
/* Negative edge manipulation */
|
62
|
+
#define B_NEG(f) ((f) & B_INV_MASK)
|
63
|
+
#define B_NOT(f) ((f) ^ B_INV_MASK)
|
64
|
+
#define B_ABS(f) ((f) & ~B_INV_MASK)
|
65
|
+
|
66
|
+
/* Constant node manipulation */
|
67
|
+
#define B_CST(f) ((f) & B_CST_MASK)
|
68
|
+
#define B_VAL(f) ((f) & B_VAL_MASK)
|
69
|
+
|
70
|
+
/* Conversion of bddp and node index/pointer */
|
71
|
+
#define B_NP(f) (Node+(B_ABS(f)>>1U))
|
72
|
+
#define B_NDX(f) (B_ABS(f)>>1U)
|
73
|
+
#define B_BDDP_NP(p) ((bddp)((p)-Node) << 1U)
|
74
|
+
|
75
|
+
/* Read & Write of bddp field in the tables */
|
76
|
+
#ifdef B_64
|
77
|
+
# define B_LOW32(f) ((bddp_32)((f)&((1ULL<<32U)-1U)))
|
78
|
+
# define B_HIGH8(f) ((bddp_h8)((f)>>32U))
|
79
|
+
# define B_SET_NXP(p, f, i) \
|
80
|
+
(p ## _h8 = f ## _h8 + i, p ## _32 = f ## _32 + i)
|
81
|
+
# define B_GET_BDDP(f) \
|
82
|
+
((bddp) f ## _32 | ((bddp) f ## _h8 << 32U))
|
83
|
+
# define B_SET_BDDP(f, g) \
|
84
|
+
(f ## _h8 = B_HIGH8(g), f ## _32 = B_LOW32(g))
|
85
|
+
# define B_CPY_BDDP(f, g) \
|
86
|
+
(f ## _h8 = g ## _h8, f ## _32 = g ## _32)
|
87
|
+
#else
|
88
|
+
# define B_SET_NXP(p, f, i) (p ## _32 = f ## _32 + i)
|
89
|
+
# define B_GET_BDDP(f) (f ## _32)
|
90
|
+
# define B_SET_BDDP(f, g) (f ## _32 = g)
|
91
|
+
# define B_CPY_BDDP(f, g) (f ## _32 = g ## _32)
|
92
|
+
#endif /* B_64 */
|
93
|
+
|
94
|
+
/* var & rfc manipulation */
|
95
|
+
#define B_VAR_NP(p) ((p)->varrfc & B_VAR_MASK)
|
96
|
+
#define B_RFC_MASK (~B_VAR_MASK)
|
97
|
+
#define B_RFC_UNIT (1U << B_VAR_WIDTH)
|
98
|
+
#define B_RFC_NP(p) ((p)->varrfc >> B_VAR_WIDTH)
|
99
|
+
#define B_RFC_ZERO_NP(p) ((p)->varrfc < B_RFC_UNIT)
|
100
|
+
#define B_RFC_ONE_NP(p) (((p)->varrfc & B_RFC_MASK) == B_RFC_UNIT)
|
101
|
+
#define B_RFC_INC_NP(p) \
|
102
|
+
(((p)->varrfc < B_RFC_MASK - B_RFC_UNIT)? \
|
103
|
+
((p)->varrfc += B_RFC_UNIT, 0) : rfc_inc_ovf(p))
|
104
|
+
#define B_RFC_DEC_NP(p) \
|
105
|
+
(((p)->varrfc >= B_RFC_MASK)? rfc_dec_ovf(p): \
|
106
|
+
(B_RFC_ZERO_NP(p))? \
|
107
|
+
err("B_RFC_DEC_NP: rfc under flow", p-Node): \
|
108
|
+
((p)->varrfc -= B_RFC_UNIT, 0))
|
109
|
+
|
110
|
+
/* ----------- Stack overflow limitter ------------ */
|
111
|
+
const int BDD_RecurLimit = 8192;
|
112
|
+
int BDD_RecurCount = 0;
|
113
|
+
#define BDD_RECUR_INC \
|
114
|
+
{if(++BDD_RecurCount >= BDD_RecurLimit) \
|
115
|
+
err("BDD_RECUR_INC: Recursion Limit", BDD_RecurCount);}
|
116
|
+
#define BDD_RECUR_DEC BDD_RecurCount--
|
117
|
+
|
118
|
+
/* Conversion of ZBDD node flag */
|
119
|
+
#define B_Z_NP(p) ((p)->f0_32 & (bddp_32)B_INV_MASK)
|
120
|
+
|
121
|
+
/* Hash Functions */
|
122
|
+
#define B_HASHKEY(f0, f1, hashSpc) \
|
123
|
+
(((B_CST(f0)? (f0): (f0)+2U) \
|
124
|
+
^(B_NEG(f0)? ~((f0)>>1U): ((f0)>>1U)) \
|
125
|
+
^(B_CST(f1)? (f1)<<1U: ((f1)+2U)<<1U) \
|
126
|
+
^(B_NEG(f1)? ~((f1)>>1U): ((f1)>>1U)) )\
|
127
|
+
& (hashSpc-1U))
|
128
|
+
/* (((f0)^((f0)>>10)^((f0)>>31)^(f1)^((f1)>>8)^((f1)>>31)) \*/
|
129
|
+
#define B_CACHEKEY(op, f, g) \
|
130
|
+
((((bddp)(op)<<2U) \
|
131
|
+
^(B_CST(f)? (f): (f)+2U) \
|
132
|
+
^(B_NEG(f)? ~((f)>>1U): ((f)>>1U)) \
|
133
|
+
^(B_CST(g)? (g)<<3U: ((g)+2U)<<3U) \
|
134
|
+
^(B_NEG(g)? ~((g)>>1U): ((g)>>1U)) )\
|
135
|
+
& (CacheSpc-1U))
|
136
|
+
|
137
|
+
/* ------- Declaration of static (internal) data ------- */
|
138
|
+
/* typedef of bddp field in the tables */
|
139
|
+
typedef unsigned int bddp_32;
|
140
|
+
#ifdef B_64
|
141
|
+
typedef unsigned char bddp_h8;
|
142
|
+
#endif
|
143
|
+
|
144
|
+
/* Declaration of Node table */
|
145
|
+
struct B_NodeTable
|
146
|
+
{
|
147
|
+
bddp_32 f0_32; /* 0-edge */
|
148
|
+
bddp_32 f1_32; /* 1-edge */
|
149
|
+
bddp_32 nx_32; /* Node index */
|
150
|
+
unsigned int varrfc; /* VarID & Reference counter */
|
151
|
+
#ifdef B_64
|
152
|
+
bddp_h8 f0_h8; /* Extention of 0-edge */
|
153
|
+
bddp_h8 f1_h8; /* Extention of 1-edge */
|
154
|
+
bddp_h8 nx_h8; /* Extention of node index */
|
155
|
+
#endif /* B_64 */
|
156
|
+
};
|
157
|
+
static struct B_NodeTable *Node = 0; /* Node Table */
|
158
|
+
static bddp NodeLimit = 0; /* Final limit size */
|
159
|
+
static bddp NodeUsed = 0; /* Number of used node */
|
160
|
+
static bddp Avail = bddnull; /* Head of available node */
|
161
|
+
static bddp NodeSpc = 0; /* Current Node-Table size */
|
162
|
+
|
163
|
+
/* Declaration of Hash-table per Var */
|
164
|
+
struct B_VarTable
|
165
|
+
{
|
166
|
+
bddp hashSpc; /* Current hash-table size */
|
167
|
+
bddp hashUsed; /* Current used entries */
|
168
|
+
bddvar lev; /* Level of the variable */
|
169
|
+
bddp_32 *hash_32; /* Hash-table */
|
170
|
+
#ifdef B_64
|
171
|
+
bddp_h8 *hash_h8; /* Extension of hash-table */
|
172
|
+
#endif /* B_64 */
|
173
|
+
};
|
174
|
+
static struct B_VarTable *Var = 0; /* Var-tables */
|
175
|
+
static bddvar *VarID = 0; /* VarID reverse table */
|
176
|
+
static bddvar VarUsed = 0; /* Number of used Var */
|
177
|
+
static bddvar VarSpc = 0; /* Current Var-table size */
|
178
|
+
|
179
|
+
/* Declaration of Operation Cache */
|
180
|
+
struct B_CacheTable
|
181
|
+
{
|
182
|
+
bddp_32 f_32; /* an operand BDD */
|
183
|
+
bddp_32 g_32; /* an operand BDD */
|
184
|
+
bddp_32 h_32; /* Result BDD */
|
185
|
+
unsigned char op; /* Operation code */
|
186
|
+
#ifdef B_64
|
187
|
+
bddp_h8 f_h8; /* Extention of an operand BDD */
|
188
|
+
bddp_h8 g_h8; /* Extention of an operand BDD */
|
189
|
+
bddp_h8 h_h8; /* Extention of result BDD */
|
190
|
+
#endif /* B_64 */
|
191
|
+
};
|
192
|
+
static struct B_CacheTable *Cache = 0; /* Opeartion cache */
|
193
|
+
static bddp CacheSpc = 0; /* Current cache size */
|
194
|
+
|
195
|
+
/* Declaration of RFC-table */
|
196
|
+
struct B_RFC_Table
|
197
|
+
{
|
198
|
+
bddp_32 nx_32; /* Node index */
|
199
|
+
bddp_32 rfc_32; /* RFC */
|
200
|
+
#ifdef B_64
|
201
|
+
bddp_h8 nx_h8; /* Extension of Node index */
|
202
|
+
bddp_h8 rfc_h8; /* Extension of RFC */
|
203
|
+
#endif /* B_64 */
|
204
|
+
};
|
205
|
+
static struct B_RFC_Table *RFCT = 0; /* RFC-Table */
|
206
|
+
static bddp RFCT_Spc; /* Current RFC-table size */
|
207
|
+
static bddp RFCT_Used; /* Current RFC-table used entries */
|
208
|
+
|
209
|
+
/* ----- Declaration of static (internal) functions ------ */
|
210
|
+
/* Private procedure */
|
211
|
+
static int err B_ARG((char *msg, bddp num));
|
212
|
+
static int rfc_inc_ovf B_ARG((struct B_NodeTable *np));
|
213
|
+
static int rfc_dec_ovf B_ARG((struct B_NodeTable *np));
|
214
|
+
static void var_enlarge B_ARG((void));
|
215
|
+
static int node_enlarge B_ARG((void));
|
216
|
+
static int hash_enlarge B_ARG((bddvar v));
|
217
|
+
static bddp getnode B_ARG((bddvar v, bddp f0, bddp f1));
|
218
|
+
static bddp getbddp B_ARG((bddvar v, bddp f0, bddp f1));
|
219
|
+
static bddp getzbddp B_ARG((bddvar v, bddp f0, bddp f1));
|
220
|
+
static bddp apply B_ARG((bddp f, bddp g, unsigned char op, unsigned char skip));
|
221
|
+
static void gc1 B_ARG((struct B_NodeTable *np));
|
222
|
+
static bddp count B_ARG((bddp f));
|
223
|
+
static void dump B_ARG((bddp f));
|
224
|
+
static void reset B_ARG((bddp f));
|
225
|
+
static void export B_ARG((FILE *strm, bddp f));
|
226
|
+
static int import B_ARG((FILE *strm, bddp *p, int lim, int z));
|
227
|
+
static int andfalse B_ARG((bddp f, bddp g));
|
228
|
+
|
229
|
+
|
230
|
+
/* ------------------ Body of program -------------------- */
|
231
|
+
/* ----------------- External functions ------------------ */
|
232
|
+
int bddinit(initsize, limitsize)
|
233
|
+
bddp initsize;
|
234
|
+
bddp limitsize;
|
235
|
+
/* Returns 1 if not enough memory (usually 0) */
|
236
|
+
{
|
237
|
+
bddp ix;
|
238
|
+
bddvar i;
|
239
|
+
|
240
|
+
/* Check dupulicate initialization */
|
241
|
+
if(Node) free(Node);
|
242
|
+
if(Var)
|
243
|
+
{
|
244
|
+
for(i=0; i<VarSpc; i++)
|
245
|
+
{
|
246
|
+
if(Var[i].hash_32) free(Var[i].hash_32);
|
247
|
+
#ifdef B_64
|
248
|
+
if(Var[i].hash_h8) free(Var[i].hash_h8);
|
249
|
+
#endif
|
250
|
+
}
|
251
|
+
free(Var);
|
252
|
+
}
|
253
|
+
if(VarID) free(VarID);
|
254
|
+
if(Cache) free(Cache);
|
255
|
+
if(RFCT) free(RFCT);
|
256
|
+
|
257
|
+
/* Set NodeLimit */
|
258
|
+
if(limitsize < B_NODE_SPC0) NodeLimit = B_NODE_SPC0;
|
259
|
+
else if(limitsize > B_NODE_MAX) NodeLimit = B_NODE_MAX;
|
260
|
+
else NodeLimit = limitsize;
|
261
|
+
|
262
|
+
/* Set NodeSpc */
|
263
|
+
if(initsize < B_NODE_SPC0) NodeSpc = B_NODE_SPC0;
|
264
|
+
else if(initsize > NodeLimit) NodeSpc = NodeLimit;
|
265
|
+
else NodeSpc = initsize;
|
266
|
+
|
267
|
+
/* Set CacheSpc */
|
268
|
+
for(CacheSpc=B_NODE_SPC0; CacheSpc<NodeSpc>>1; CacheSpc<<=1U)
|
269
|
+
; /* empty */
|
270
|
+
|
271
|
+
/* Set VarSpc */
|
272
|
+
VarSpc = B_VAR_SPC0;
|
273
|
+
|
274
|
+
/* Memory allocation */
|
275
|
+
Node = B_MALLOC(struct B_NodeTable, NodeSpc);
|
276
|
+
Var = B_MALLOC(struct B_VarTable, VarSpc);
|
277
|
+
VarID = B_MALLOC(bddvar, VarSpc);
|
278
|
+
Cache = B_MALLOC(struct B_CacheTable, CacheSpc);
|
279
|
+
|
280
|
+
/* Check overflow */
|
281
|
+
if(Node == 0 || Var == 0 || VarID == 0 || Cache == 0)
|
282
|
+
{
|
283
|
+
if(Cache){ free(Cache); Cache = 0; }
|
284
|
+
if(VarID){ free(VarID); VarID = 0; }
|
285
|
+
if(Var){ free(Var); Var = 0; }
|
286
|
+
if(Node){ free(Node); Node = 0; }
|
287
|
+
NodeLimit = 0;
|
288
|
+
return 1;
|
289
|
+
}
|
290
|
+
|
291
|
+
/* Initialize */
|
292
|
+
NodeUsed = 0;
|
293
|
+
Node[NodeSpc-1U].varrfc = 0;
|
294
|
+
B_SET_BDDP(Node[NodeSpc-1U].nx, bddnull);
|
295
|
+
for(ix=0; ix<NodeSpc-1U; ix++)
|
296
|
+
{
|
297
|
+
Node[ix].varrfc = 0;
|
298
|
+
B_SET_BDDP(Node[ix].nx, ix+1U);
|
299
|
+
}
|
300
|
+
Avail = 0;
|
301
|
+
|
302
|
+
VarUsed = 0;
|
303
|
+
for(i=0; i<VarSpc; i++)
|
304
|
+
{
|
305
|
+
Var[i].hashSpc = 0;
|
306
|
+
Var[i].hashUsed = 0;
|
307
|
+
Var[i].lev = i;
|
308
|
+
VarID[i] = i;
|
309
|
+
Var[i].hash_32 = 0;
|
310
|
+
#ifdef B_64
|
311
|
+
Var[i].hash_h8 = 0;
|
312
|
+
#endif
|
313
|
+
}
|
314
|
+
|
315
|
+
for(ix=0; ix<CacheSpc; ix++) Cache[ix].op = BC_NULL;
|
316
|
+
|
317
|
+
RFCT_Spc = 0;
|
318
|
+
RFCT_Used = 0;
|
319
|
+
|
320
|
+
return 0;
|
321
|
+
}
|
322
|
+
|
323
|
+
bddp bddcopy(f)
|
324
|
+
bddp f;
|
325
|
+
{
|
326
|
+
struct B_NodeTable *fp;
|
327
|
+
|
328
|
+
if(f == bddnull) return bddnull;
|
329
|
+
if(B_CST(f)) return f; /* Constant */
|
330
|
+
fp = B_NP(f);
|
331
|
+
if(fp >= Node+NodeSpc || fp->varrfc == 0)
|
332
|
+
err("bddcopy: Invalid bddp", f);
|
333
|
+
B_RFC_INC_NP(fp);
|
334
|
+
return f;
|
335
|
+
}
|
336
|
+
|
337
|
+
void bddfree(f)
|
338
|
+
bddp f;
|
339
|
+
{
|
340
|
+
struct B_NodeTable *fp;
|
341
|
+
|
342
|
+
if(f == bddnull) return;
|
343
|
+
if(B_CST(f)) return; /* Constant */
|
344
|
+
fp = B_NP(f);
|
345
|
+
if(fp >= Node+NodeSpc || fp->varrfc == 0)
|
346
|
+
err("bddfree: Invalid bddp", f);
|
347
|
+
B_RFC_DEC_NP(fp);
|
348
|
+
}
|
349
|
+
|
350
|
+
int bddgc()
|
351
|
+
/* Returns 1 if there are no free node (usually 0) */
|
352
|
+
{
|
353
|
+
bddp i, n, f;
|
354
|
+
struct B_NodeTable *fp;
|
355
|
+
struct B_CacheTable *cachep;
|
356
|
+
struct B_NodeTable *np;
|
357
|
+
struct B_VarTable *varp;
|
358
|
+
bddvar v;
|
359
|
+
bddp oldSpc, newSpc, nx, key, f0, f1;
|
360
|
+
bddp_32 *newhash_32, *p_32, *p2_32;
|
361
|
+
#ifdef B_64
|
362
|
+
bddp_h8 *newhash_h8, *p_h8, *p2_h8;
|
363
|
+
#endif
|
364
|
+
|
365
|
+
n = NodeUsed;
|
366
|
+
for(fp=Node; fp<Node+NodeSpc; fp++)
|
367
|
+
if(fp->varrfc != 0 && B_RFC_ZERO_NP(fp))
|
368
|
+
gc1(fp);
|
369
|
+
if(n == NodeUsed) return 1; /* No free node */
|
370
|
+
|
371
|
+
/* Cache clear */
|
372
|
+
for(cachep=Cache; cachep<Cache+CacheSpc; cachep++)
|
373
|
+
{
|
374
|
+
switch(cachep->op)
|
375
|
+
{
|
376
|
+
case BC_NULL:
|
377
|
+
break;
|
378
|
+
case BC_AND:
|
379
|
+
case BC_XOR:
|
380
|
+
case BC_INTERSEC:
|
381
|
+
case BC_UNION:
|
382
|
+
case BC_SUBTRACT:
|
383
|
+
case BC_CHANGE:
|
384
|
+
f = B_GET_BDDP(cachep->f);
|
385
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
386
|
+
{
|
387
|
+
cachep->op = BC_NULL;
|
388
|
+
break;
|
389
|
+
}
|
390
|
+
f = B_GET_BDDP(cachep->g);
|
391
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
392
|
+
{
|
393
|
+
cachep->op = BC_NULL;
|
394
|
+
break;
|
395
|
+
}
|
396
|
+
f = B_GET_BDDP(cachep->h);
|
397
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
398
|
+
{
|
399
|
+
cachep->op = BC_NULL;
|
400
|
+
break;
|
401
|
+
}
|
402
|
+
break;
|
403
|
+
case BC_AT0:
|
404
|
+
case BC_AT1:
|
405
|
+
case BC_OFFSET:
|
406
|
+
case BC_ONSET:
|
407
|
+
f = B_GET_BDDP(cachep->f);
|
408
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
409
|
+
{
|
410
|
+
cachep->op = BC_NULL;
|
411
|
+
break;
|
412
|
+
}
|
413
|
+
f = B_GET_BDDP(cachep->h);
|
414
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
415
|
+
{
|
416
|
+
cachep->op = BC_NULL;
|
417
|
+
break;
|
418
|
+
}
|
419
|
+
break;
|
420
|
+
case BC_CARD:
|
421
|
+
case BC_LIT:
|
422
|
+
case BC_LEN:
|
423
|
+
f = B_GET_BDDP(cachep->f);
|
424
|
+
if(!B_CST(f) && (fp=B_NP(f))<Node+NodeSpc && fp->varrfc == 0)
|
425
|
+
{
|
426
|
+
cachep->op = BC_NULL;
|
427
|
+
break;
|
428
|
+
}
|
429
|
+
break;
|
430
|
+
default:
|
431
|
+
cachep->op = BC_NULL;
|
432
|
+
break;
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
/* Hash-table packing */
|
437
|
+
for(v=1; v<=VarUsed; v++)
|
438
|
+
{
|
439
|
+
varp = &Var[v];
|
440
|
+
|
441
|
+
/* Get new size */
|
442
|
+
oldSpc = varp->hashSpc;
|
443
|
+
newSpc = oldSpc;
|
444
|
+
while(newSpc > B_HASH_SPC0)
|
445
|
+
{
|
446
|
+
if(newSpc>>2 < varp->hashUsed) break;
|
447
|
+
newSpc >>= 1;
|
448
|
+
}
|
449
|
+
if(newSpc == oldSpc) continue;
|
450
|
+
|
451
|
+
/* Reduce space */
|
452
|
+
#ifdef B_64
|
453
|
+
newhash_32 = B_MALLOC(bddp_32, newSpc);
|
454
|
+
newhash_h8 = B_MALLOC(bddp_h8, newSpc);
|
455
|
+
if(!newhash_32 || !newhash_h8)
|
456
|
+
{
|
457
|
+
if(newhash_32) free(newhash_32);
|
458
|
+
if(newhash_h8) free(newhash_h8);
|
459
|
+
break; /* Not enough memory */
|
460
|
+
}
|
461
|
+
#else
|
462
|
+
newhash_32 = B_MALLOC(bddp_32, newSpc);
|
463
|
+
if(!newhash_32) break; /* Not enough memory */
|
464
|
+
#endif
|
465
|
+
|
466
|
+
/* Initialize new hash entry */
|
467
|
+
for(i=0; i<newSpc; i++)
|
468
|
+
{
|
469
|
+
B_SET_NXP(p, newhash, i);
|
470
|
+
B_SET_BDDP(*p, bddnull);
|
471
|
+
}
|
472
|
+
|
473
|
+
/* restore hash entry */
|
474
|
+
for(i=0; i<oldSpc; i++)
|
475
|
+
{
|
476
|
+
key = i & (newSpc-1U);
|
477
|
+
np = 0;
|
478
|
+
B_SET_NXP(p, newhash, key);
|
479
|
+
nx = B_GET_BDDP(*p);
|
480
|
+
while(nx != bddnull)
|
481
|
+
{
|
482
|
+
np = Node + nx;
|
483
|
+
nx = B_GET_BDDP(np->nx);
|
484
|
+
}
|
485
|
+
if(np) { B_SET_NXP(p2, varp->hash, i); B_CPY_BDDP(np->nx, *p2); }
|
486
|
+
else
|
487
|
+
{
|
488
|
+
B_SET_NXP(p, newhash, key);
|
489
|
+
B_SET_NXP(p2, varp->hash, i);
|
490
|
+
B_CPY_BDDP(*p, *p2);
|
491
|
+
}
|
492
|
+
}
|
493
|
+
varp->hashSpc = newSpc;
|
494
|
+
free(varp->hash_32);
|
495
|
+
varp->hash_32 = newhash_32;
|
496
|
+
#ifdef B_64
|
497
|
+
free(varp->hash_h8);
|
498
|
+
varp->hash_h8 = newhash_h8;
|
499
|
+
#endif
|
500
|
+
}
|
501
|
+
return 0;
|
502
|
+
}
|
503
|
+
|
504
|
+
bddp bddused() { return NodeUsed; }
|
505
|
+
|
506
|
+
bddp bddsize(f)
|
507
|
+
bddp f;
|
508
|
+
/* Returns 0 for bddnull */
|
509
|
+
{
|
510
|
+
bddp num;
|
511
|
+
struct B_NodeTable *fp;
|
512
|
+
|
513
|
+
if(f == bddnull) return 0;
|
514
|
+
if(B_CST(f)) return 0; /* Constant */
|
515
|
+
if((fp=B_NP(f))>=Node+NodeSpc || fp->varrfc == 0)
|
516
|
+
err("bddsize: Invalid bddp", f);
|
517
|
+
|
518
|
+
num = count(f);
|
519
|
+
reset(f);
|
520
|
+
return num;
|
521
|
+
}
|
522
|
+
|
523
|
+
bddp bddvsize(p, lim)
|
524
|
+
bddp *p;
|
525
|
+
int lim;
|
526
|
+
/* Returns 0 for bddnull */
|
527
|
+
{
|
528
|
+
bddp num;
|
529
|
+
struct B_NodeTable *fp;
|
530
|
+
int n, i;
|
531
|
+
|
532
|
+
/* Check operand */
|
533
|
+
n = lim;
|
534
|
+
for(i=0; i<n; i++)
|
535
|
+
{
|
536
|
+
if(p[i] == bddnull)
|
537
|
+
{
|
538
|
+
n = i;
|
539
|
+
break;
|
540
|
+
}
|
541
|
+
if(!B_CST(p[i])&&
|
542
|
+
((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
|
543
|
+
err("bddvsize: Invalid bddp", p[i]);
|
544
|
+
}
|
545
|
+
num = 0;
|
546
|
+
for(i=0; i<n; i++) num += count(p[i]);
|
547
|
+
for(i=0; i<n; i++) reset(p[i]);
|
548
|
+
return num;
|
549
|
+
}
|
550
|
+
|
551
|
+
void bddexport(strm, p, lim)
|
552
|
+
FILE *strm;
|
553
|
+
bddp *p;
|
554
|
+
int lim;
|
555
|
+
{
|
556
|
+
struct B_NodeTable *fp;
|
557
|
+
int n, i, lev, lev0;
|
558
|
+
|
559
|
+
/* Check operands */
|
560
|
+
n = lim;
|
561
|
+
lev = 0;
|
562
|
+
for(i=0; i<n; i++)
|
563
|
+
{
|
564
|
+
if(p[i] == bddnull)
|
565
|
+
{
|
566
|
+
n = i;
|
567
|
+
break;
|
568
|
+
}
|
569
|
+
if(!B_CST(p[i])&&
|
570
|
+
((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
|
571
|
+
err("bddvexport: Invalid bddp", p[i]);
|
572
|
+
lev0 = bddlevofvar(bddtop(p[i]));
|
573
|
+
if(lev0 > lev) lev = lev0;
|
574
|
+
}
|
575
|
+
|
576
|
+
fprintf(strm, "_i %d\n_o %d\n_n ", lev, n);
|
577
|
+
fprintf(strm, B_BDDP_FD, bddvsize(p, n));
|
578
|
+
fprintf(strm, "\n");
|
579
|
+
|
580
|
+
/* Put internal nodes */
|
581
|
+
for(i=0; i<n; i++) export(strm, p[i]);
|
582
|
+
for(i=0; i<n; i++) reset(p[i]);
|
583
|
+
|
584
|
+
/* Put external node */
|
585
|
+
for(i=0; i<n; i++)
|
586
|
+
{
|
587
|
+
if(p[i] == bddfalse) fprintf(strm, "F");
|
588
|
+
else if(p[i] == bddtrue) fprintf(strm, "T");
|
589
|
+
else fprintf(strm, B_BDDP_FD, p[i]);
|
590
|
+
fprintf(strm, "\n");
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
594
|
+
void bdddump(f)
|
595
|
+
bddp f;
|
596
|
+
{
|
597
|
+
struct B_NodeTable *fp;
|
598
|
+
|
599
|
+
/* Check indexes */
|
600
|
+
if(f == bddnull) { printf("RT = NULL\n\n"); return; }
|
601
|
+
if(!B_CST(f)&&
|
602
|
+
((fp=B_NP(f))>=Node+NodeSpc || fp->varrfc==0))
|
603
|
+
err("bdddump: Invalid bddp", f);
|
604
|
+
|
605
|
+
/* Dump nodes */
|
606
|
+
dump(f);
|
607
|
+
reset(f);
|
608
|
+
|
609
|
+
/* Dump top node */
|
610
|
+
printf("RT = ");
|
611
|
+
if(B_NEG(f)) putchar('~');
|
612
|
+
if(B_CST(f)) printf(B_BDDP_FD, B_ABS(B_VAL(f)));
|
613
|
+
else { printf("N"); printf(B_BDDP_FD, B_NDX(f)); }
|
614
|
+
printf("\n\n");
|
615
|
+
}
|
616
|
+
|
617
|
+
void bddvdump(p, n)
|
618
|
+
bddp *p;
|
619
|
+
int n;
|
620
|
+
{
|
621
|
+
struct B_NodeTable *fp;
|
622
|
+
int i;
|
623
|
+
|
624
|
+
/* Check operands */
|
625
|
+
for(i=0; i<n; i++)
|
626
|
+
{
|
627
|
+
if(p[i] == bddnull) return;
|
628
|
+
if(!B_CST(p[i])&&
|
629
|
+
((fp=B_NP(p[i]))>=Node+NodeSpc || fp->varrfc==0))
|
630
|
+
err("bddvdump: Invalid bddp", p[i]);
|
631
|
+
}
|
632
|
+
|
633
|
+
/* Dump nodes */
|
634
|
+
for(i=0; i<n; i++) if(p[i] != bddnull) dump(p[i]);
|
635
|
+
for(i=0; i<n; i++) if(p[i] != bddnull) reset(p[i]);
|
636
|
+
|
637
|
+
/* Dump top node */
|
638
|
+
for(i=0; i<n; i++)
|
639
|
+
{
|
640
|
+
printf("RT%d = ", i);
|
641
|
+
if(p[i] == bddnull) printf("NULL");
|
642
|
+
else
|
643
|
+
{
|
644
|
+
if(B_NEG(p[i])) putchar('~');
|
645
|
+
if(B_CST(p[i])) printf(B_BDDP_FD, B_ABS(B_VAL(p[i])));
|
646
|
+
else { printf("N"); printf(B_BDDP_FD, B_NDX(p[i])); }
|
647
|
+
}
|
648
|
+
putchar('\n');
|
649
|
+
}
|
650
|
+
printf("\n");
|
651
|
+
}
|
652
|
+
|
653
|
+
bddp bddrcache(op, f, g)
|
654
|
+
unsigned char op;
|
655
|
+
bddp f, g;
|
656
|
+
{
|
657
|
+
struct B_CacheTable *cachep;
|
658
|
+
|
659
|
+
cachep = Cache + B_CACHEKEY(op, f, g);
|
660
|
+
if(op == cachep->op &&
|
661
|
+
f == B_GET_BDDP(cachep->f) &&
|
662
|
+
g == B_GET_BDDP(cachep->g))
|
663
|
+
return B_GET_BDDP(cachep->h); /* Hit */
|
664
|
+
return bddnull;
|
665
|
+
}
|
666
|
+
|
667
|
+
void bddwcache(op, f, g, h)
|
668
|
+
unsigned char op;
|
669
|
+
bddp f, g, h;
|
670
|
+
{
|
671
|
+
struct B_CacheTable *cachep;
|
672
|
+
|
673
|
+
if(op < 20) err("bddwcache: op < 20", op);
|
674
|
+
if(h == bddnull) return;
|
675
|
+
cachep = Cache + B_CACHEKEY(op, f, g);
|
676
|
+
cachep->op = op;
|
677
|
+
B_SET_BDDP(cachep->f, f);
|
678
|
+
B_SET_BDDP(cachep->g, g);
|
679
|
+
B_SET_BDDP(cachep->h, h);
|
680
|
+
}
|
681
|
+
|
682
|
+
bddp bddnot(f)
|
683
|
+
bddp f;
|
684
|
+
{
|
685
|
+
if(f == bddnull) return bddnull;
|
686
|
+
return B_NOT(bddcopy(f));
|
687
|
+
}
|
688
|
+
|
689
|
+
bddvar bddlevofvar(v)
|
690
|
+
bddvar v;
|
691
|
+
{
|
692
|
+
if(v > VarUsed)
|
693
|
+
err("bddlevofvar: Invalid VarID", v);
|
694
|
+
return Var[v].lev;
|
695
|
+
}
|
696
|
+
|
697
|
+
bddvar bddvaroflev(lev)
|
698
|
+
bddvar lev;
|
699
|
+
{
|
700
|
+
if(lev > VarUsed)
|
701
|
+
err("bddvaroflev: Invalid level", lev);
|
702
|
+
return VarID[lev];
|
703
|
+
}
|
704
|
+
|
705
|
+
bddvar bddvarused()
|
706
|
+
{
|
707
|
+
return VarUsed;
|
708
|
+
}
|
709
|
+
|
710
|
+
bddvar bddnewvar()
|
711
|
+
{
|
712
|
+
if(++VarUsed == VarSpc) var_enlarge();
|
713
|
+
return VarUsed;
|
714
|
+
}
|
715
|
+
|
716
|
+
bddvar bddnewvaroflev(lev)
|
717
|
+
bddvar lev;
|
718
|
+
{
|
719
|
+
bddvar i, v;
|
720
|
+
|
721
|
+
if(lev == 0 || lev > ++VarUsed)
|
722
|
+
err("bddnewvaroflev: Invalid level", lev);
|
723
|
+
if(VarUsed == VarSpc) var_enlarge();
|
724
|
+
for(i=VarUsed; i>lev; i--) Var[ VarID[i] = VarID[i-1U] ].lev = i;
|
725
|
+
Var[ VarID[lev] = VarUsed ].lev = lev;
|
726
|
+
return VarUsed;
|
727
|
+
}
|
728
|
+
|
729
|
+
bddvar bddtop(f)
|
730
|
+
bddp f;
|
731
|
+
{
|
732
|
+
struct B_NodeTable *fp;
|
733
|
+
|
734
|
+
if(f == bddnull) return 0;
|
735
|
+
if(B_CST(f)) return 0; /* Constant */
|
736
|
+
fp = B_NP(f);
|
737
|
+
if(fp >= Node+NodeSpc || fp->varrfc == 0)
|
738
|
+
err("bddtop: Invalid bddp", f);
|
739
|
+
return B_VAR_NP(fp);
|
740
|
+
}
|
741
|
+
|
742
|
+
bddp bddprime(v)
|
743
|
+
bddvar v;
|
744
|
+
/* Returns bddnull if not enough memory */
|
745
|
+
{
|
746
|
+
if(v == 0 || v > VarUsed)
|
747
|
+
err("bddprime: Invalid VarID", v);
|
748
|
+
return getbddp(v, bddfalse, bddtrue);
|
749
|
+
}
|
750
|
+
|
751
|
+
|
752
|
+
bddp bddand(f, g)
|
753
|
+
bddp f, g;
|
754
|
+
/* Returns bddnull if not enough memory */
|
755
|
+
{
|
756
|
+
struct B_NodeTable *fp;
|
757
|
+
|
758
|
+
/* Check operands */
|
759
|
+
if(f == bddnull) return bddnull;
|
760
|
+
if(g == bddnull) return bddnull;
|
761
|
+
if(B_CST(f))
|
762
|
+
{ if(B_ABS(f) != bddfalse) err("bddand: Invalid bddp", f); }
|
763
|
+
else
|
764
|
+
{
|
765
|
+
fp = B_NP(f);
|
766
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
767
|
+
err("bddand: Invalid bddp", f);
|
768
|
+
if(B_Z_NP(fp)) err("bddand: applying ZBDD node", f);
|
769
|
+
}
|
770
|
+
if(B_CST(g))
|
771
|
+
{ if(B_ABS(g) != bddfalse) err("bddand: Invalid bddp", g); }
|
772
|
+
else
|
773
|
+
{
|
774
|
+
fp = B_NP(g);
|
775
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
776
|
+
err("bddand: Invalid bddp", g);
|
777
|
+
if(B_Z_NP(fp)) err("bddand: applying ZBDD node", g);
|
778
|
+
}
|
779
|
+
|
780
|
+
return apply(f, g, BC_AND, 0);
|
781
|
+
}
|
782
|
+
|
783
|
+
bddp bddor(f, g)
|
784
|
+
bddp f, g;
|
785
|
+
/* Returns bddnull if not enough memory */
|
786
|
+
{
|
787
|
+
bddp h;
|
788
|
+
|
789
|
+
if(f == bddnull) return bddnull;
|
790
|
+
if(g == bddnull) return bddnull;
|
791
|
+
h = bddand(B_NOT(f), B_NOT(g));
|
792
|
+
if(h == bddnull) return bddnull;
|
793
|
+
return B_NOT(h);
|
794
|
+
}
|
795
|
+
|
796
|
+
bddp bddxor(f, g)
|
797
|
+
bddp f, g;
|
798
|
+
/* Returns bddnull if not enough memory */
|
799
|
+
{
|
800
|
+
struct B_NodeTable *fp;
|
801
|
+
|
802
|
+
/* Check operands */
|
803
|
+
if(f == bddnull) return bddnull;
|
804
|
+
if(g == bddnull) return bddnull;
|
805
|
+
if(B_CST(f))
|
806
|
+
{ if(B_ABS(f) != bddfalse) err("bddand: Invalid bddp", f); }
|
807
|
+
else
|
808
|
+
{
|
809
|
+
fp = B_NP(f);
|
810
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
811
|
+
err("bddxor: Invalid bddp", f);
|
812
|
+
if(B_Z_NP(fp)) err("bddand: applying ZBDD node", f);
|
813
|
+
}
|
814
|
+
if(B_CST(g))
|
815
|
+
{ if(B_ABS(g) != bddfalse) err("bddand: Invalid bddp", g); }
|
816
|
+
else
|
817
|
+
{
|
818
|
+
fp = B_NP(g);
|
819
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
820
|
+
err("bddxor: Invalid bddp", g);
|
821
|
+
if(B_Z_NP(fp)) err("bddand: applying ZBDD node", g);
|
822
|
+
}
|
823
|
+
|
824
|
+
return apply(f, g, BC_XOR, 0);
|
825
|
+
}
|
826
|
+
|
827
|
+
bddp bddnand(f, g)
|
828
|
+
bddp f, g;
|
829
|
+
/* Returns bddnull if not enough memory */
|
830
|
+
{
|
831
|
+
bddp h;
|
832
|
+
|
833
|
+
h = bddand(f, g);
|
834
|
+
if(h == bddnull) return bddnull;
|
835
|
+
return B_NOT(h);
|
836
|
+
}
|
837
|
+
|
838
|
+
bddp bddnor(f, g)
|
839
|
+
bddp f, g;
|
840
|
+
/* Returns bddnull if not enough memory */
|
841
|
+
{
|
842
|
+
if(f == bddnull) return bddnull;
|
843
|
+
if(g == bddnull) return bddnull;
|
844
|
+
return bddand(B_NOT(f), B_NOT(g));
|
845
|
+
}
|
846
|
+
|
847
|
+
bddp bddxnor(f, g)
|
848
|
+
bddp f, g;
|
849
|
+
/* Returns bddnull if not enough memory */
|
850
|
+
{
|
851
|
+
if(g == bddnull) return bddnull;
|
852
|
+
return bddxor(f, B_NOT(g));
|
853
|
+
}
|
854
|
+
|
855
|
+
bddp bddcofactor(f, g)
|
856
|
+
bddp f, g;
|
857
|
+
/* Returns bddnull if not enough memory */
|
858
|
+
{
|
859
|
+
struct B_NodeTable *fp;
|
860
|
+
|
861
|
+
/* Check operands */
|
862
|
+
if(f == bddnull) return bddnull;
|
863
|
+
if(g == bddnull) return bddnull;
|
864
|
+
if(B_CST(f))
|
865
|
+
{ if(B_ABS(f) != bddfalse) err("bddcofactor: Invalid bddp", f); }
|
866
|
+
else
|
867
|
+
{
|
868
|
+
fp = B_NP(f);
|
869
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
870
|
+
err("bddcofactor: Invalid bddp", f);
|
871
|
+
if(B_Z_NP(fp)) err("bddcofactor: applying ZBDD node", f);
|
872
|
+
}
|
873
|
+
if(B_CST(g))
|
874
|
+
{ if(B_ABS(g) != bddfalse) err("bddcofactor: Invalid bddp", g); }
|
875
|
+
else
|
876
|
+
{
|
877
|
+
fp = B_NP(g);
|
878
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
879
|
+
err("bddcofactor: Invalid bddp", g);
|
880
|
+
if(B_Z_NP(fp)) err("bddcofactor: applying ZBDD node", g);
|
881
|
+
}
|
882
|
+
|
883
|
+
return apply(f, g, BC_COFACTOR, 0);
|
884
|
+
}
|
885
|
+
|
886
|
+
bddp bdduniv(f, g)
|
887
|
+
bddp f, g;
|
888
|
+
/* Returns bddnull if not enough memory */
|
889
|
+
{
|
890
|
+
struct B_NodeTable *fp;
|
891
|
+
|
892
|
+
/* Check operands */
|
893
|
+
if(f == bddnull) return bddnull;
|
894
|
+
if(g == bddnull) return bddnull;
|
895
|
+
if(B_CST(f))
|
896
|
+
{ if(B_ABS(f) != bddfalse) err("bdduniv: Invalid bddp", f); }
|
897
|
+
else
|
898
|
+
{
|
899
|
+
fp = B_NP(f);
|
900
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
901
|
+
err("bdduniv: Invalid bddp", f);
|
902
|
+
if(B_Z_NP(fp)) err("bdduniv: applying ZBDD node", f);
|
903
|
+
}
|
904
|
+
if(B_CST(g))
|
905
|
+
{ if(B_ABS(g) != bddfalse) err("bdduniv: Invalid bddp", g); }
|
906
|
+
else
|
907
|
+
{
|
908
|
+
fp = B_NP(g);
|
909
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
910
|
+
err("bdduniv: Invalid bddp", g);
|
911
|
+
if(B_Z_NP(fp)) err("bdduniv: applying ZBDD node", g);
|
912
|
+
}
|
913
|
+
|
914
|
+
return apply(f, g, BC_UNIV, 0);
|
915
|
+
}
|
916
|
+
|
917
|
+
bddp bddexist(f, g)
|
918
|
+
bddp f, g;
|
919
|
+
/* Returns bddnull if not enough memory */
|
920
|
+
{
|
921
|
+
bddp h;
|
922
|
+
|
923
|
+
if(f == bddnull) return bddnull;
|
924
|
+
if(g == bddnull) return bddnull;
|
925
|
+
h = bdduniv(B_NOT(f), g);
|
926
|
+
if(h == bddnull) return bddnull;
|
927
|
+
return B_NOT(h);
|
928
|
+
}
|
929
|
+
|
930
|
+
int bddimply(f, g)
|
931
|
+
bddp f, g;
|
932
|
+
{
|
933
|
+
struct B_NodeTable *fp;
|
934
|
+
|
935
|
+
/* Check operands */
|
936
|
+
if(f == bddnull) return 0;
|
937
|
+
if(g == bddnull) return 0;
|
938
|
+
if(B_CST(f))
|
939
|
+
{ if(B_ABS(f) != bddfalse) err("bddimply: Invalid bddp", f); }
|
940
|
+
else
|
941
|
+
{
|
942
|
+
fp = B_NP(f);
|
943
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
944
|
+
err("bddimply: Invalid bddp", f);
|
945
|
+
if(B_Z_NP(fp)) err("bddimply: applying ZBDD node", f);
|
946
|
+
}
|
947
|
+
if(B_CST(g))
|
948
|
+
{ if(B_ABS(g) != bddfalse) err("bddimply: Invalid bddp", g); }
|
949
|
+
else
|
950
|
+
{
|
951
|
+
fp = B_NP(g);
|
952
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
953
|
+
err("bddimply: Invalid bddp", g);
|
954
|
+
if(B_Z_NP(fp)) err("bddimply: applying ZBDD node", g);
|
955
|
+
}
|
956
|
+
|
957
|
+
return ! andfalse(f, B_NOT(g));
|
958
|
+
}
|
959
|
+
|
960
|
+
bddp bddsupport(f)
|
961
|
+
bddp f;
|
962
|
+
/* Returns bddnull if not enough memory */
|
963
|
+
{
|
964
|
+
struct B_NodeTable *fp;
|
965
|
+
|
966
|
+
/* Check operands */
|
967
|
+
if(f == bddnull) return bddnull;
|
968
|
+
if(B_CST(f)) return bddfalse;
|
969
|
+
fp = B_NP(f);
|
970
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
971
|
+
err("bddsupport: Invalid bddp", f);
|
972
|
+
|
973
|
+
return apply(f, bddfalse, BC_SUPPORT, 0);
|
974
|
+
}
|
975
|
+
|
976
|
+
bddp bddat0(f, v)
|
977
|
+
bddp f;
|
978
|
+
bddvar v;
|
979
|
+
/* Returns bddnull if not enough memory */
|
980
|
+
{
|
981
|
+
struct B_NodeTable *fp;
|
982
|
+
|
983
|
+
/* Check operands */
|
984
|
+
if(v > VarUsed || v == 0) err("bddat0: Invalid VarID", v);
|
985
|
+
if(f == bddnull) return bddnull;
|
986
|
+
if(B_CST(f)) return f;
|
987
|
+
fp = B_NP(f);
|
988
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
989
|
+
err("bddat0: Invalid bddp", f);
|
990
|
+
|
991
|
+
return apply(f, (bddp)v, BC_AT0, 0);
|
992
|
+
}
|
993
|
+
|
994
|
+
bddp bddat1(f, v)
|
995
|
+
bddp f;
|
996
|
+
bddvar v;
|
997
|
+
/* Returns bddnull if not enough memory */
|
998
|
+
{
|
999
|
+
struct B_NodeTable *fp;
|
1000
|
+
|
1001
|
+
/* Check operands */
|
1002
|
+
if(v > VarUsed || v == 0) err("bddat1: Invalid VarID", v);
|
1003
|
+
if(f == bddnull) return bddnull;
|
1004
|
+
if(B_CST(f)) return f;
|
1005
|
+
fp = B_NP(f);
|
1006
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1007
|
+
err("bddat1: Invalid bddp", f);
|
1008
|
+
|
1009
|
+
return apply(f, (bddp)v, BC_AT1, 0);
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
bddp bddlshift(f, shift)
|
1013
|
+
bddp f;
|
1014
|
+
bddvar shift;
|
1015
|
+
/* Returns bddnull if not enough memory */
|
1016
|
+
{
|
1017
|
+
struct B_NodeTable *fp;
|
1018
|
+
bddvar flev;
|
1019
|
+
|
1020
|
+
/* Check operands */
|
1021
|
+
if(shift >= VarUsed)
|
1022
|
+
err("bddlshift: Invalid shift", shift);
|
1023
|
+
if(f == bddnull) return bddnull;
|
1024
|
+
if(B_CST(f)) return f;
|
1025
|
+
if(shift == 0) return bddcopy(f);
|
1026
|
+
if((fp=B_NP(f))>=Node+NodeSpc || !fp->varrfc)
|
1027
|
+
err("bddlshift: Invalid bddp", f);
|
1028
|
+
|
1029
|
+
return apply(f, (bddp)shift, BC_LSHIFT, 0);
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
bddp bddrshift(f, shift)
|
1033
|
+
bddp f;
|
1034
|
+
bddvar shift;
|
1035
|
+
/* Returns bddnull if not enough memory */
|
1036
|
+
{
|
1037
|
+
struct B_NodeTable *fp;
|
1038
|
+
bddvar flev;
|
1039
|
+
|
1040
|
+
/* Check operands */
|
1041
|
+
if(shift >= VarUsed)
|
1042
|
+
err("bddrshift: Invalid shift", shift);
|
1043
|
+
if(f == bddnull) return bddnull;
|
1044
|
+
if(B_CST(f)) return f;
|
1045
|
+
if(shift == 0) return bddcopy(f);
|
1046
|
+
if((fp=B_NP(f))>=Node+NodeSpc || !fp->varrfc)
|
1047
|
+
err("bddrshift: Invalid bddp", f);
|
1048
|
+
|
1049
|
+
return apply(f, (bddp)shift, BC_RSHIFT, 0);
|
1050
|
+
}
|
1051
|
+
|
1052
|
+
bddp bddoffset(f, v)
|
1053
|
+
bddp f;
|
1054
|
+
bddvar v;
|
1055
|
+
/* Returns bddnull if not enough memory */
|
1056
|
+
{
|
1057
|
+
struct B_NodeTable *fp;
|
1058
|
+
|
1059
|
+
/* Check operands */
|
1060
|
+
if(v > VarUsed || v == 0) err("bddoffset: Invalid VarID", v);
|
1061
|
+
if(f == bddnull) return bddnull;
|
1062
|
+
if(B_CST(f)) return f;
|
1063
|
+
fp = B_NP(f);
|
1064
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1065
|
+
err("bddoffset: Invalid bddp", f);
|
1066
|
+
if(!B_Z_NP(fp)) err("bddoffset: applying non-ZBDD node", f);
|
1067
|
+
|
1068
|
+
return apply(f, (bddp)v, BC_OFFSET, 0);
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
bddp bddonset0(f, v)
|
1072
|
+
bddp f;
|
1073
|
+
bddvar v;
|
1074
|
+
/* Returns bddnull if not enough memory */
|
1075
|
+
{
|
1076
|
+
struct B_NodeTable *fp;
|
1077
|
+
|
1078
|
+
/* Check operands */
|
1079
|
+
if(v > VarUsed || v == 0) err("bddonset0: Invalid VarID", v);
|
1080
|
+
if(f == bddnull) return bddnull;
|
1081
|
+
if(B_CST(f)) return bddfalse;
|
1082
|
+
fp = B_NP(f);
|
1083
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1084
|
+
err("bddonset0: Invalid bddp", f);
|
1085
|
+
if(!B_Z_NP(fp)) err("bddonset0: applying non-ZBDD node", f);
|
1086
|
+
|
1087
|
+
return apply(f, (bddp)v, BC_ONSET, 0);
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
bddp bddonset(f, v)
|
1091
|
+
bddp f;
|
1092
|
+
bddvar v;
|
1093
|
+
/* Returns bddnull if not enough memory */
|
1094
|
+
{
|
1095
|
+
bddp g, h;
|
1096
|
+
|
1097
|
+
g = bddonset0(f, v);
|
1098
|
+
h = bddchange(g, v);
|
1099
|
+
bddfree(g);
|
1100
|
+
return h;
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
bddp bddchange(f, v)
|
1104
|
+
bddp f;
|
1105
|
+
bddvar v;
|
1106
|
+
/* Returns bddnull if not enough memory */
|
1107
|
+
{
|
1108
|
+
struct B_NodeTable *fp;
|
1109
|
+
|
1110
|
+
/* Check operands */
|
1111
|
+
if(v > VarUsed || v == 0) err("bddchange: Invalid VarID", v);
|
1112
|
+
if(f == bddnull) return bddnull;
|
1113
|
+
if(!B_CST(f))
|
1114
|
+
{
|
1115
|
+
fp = B_NP(f);
|
1116
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1117
|
+
err("bddchange: Invalid bddp", f);
|
1118
|
+
if(!B_Z_NP(fp)) err("bddchange: applying non-ZBDD node", f);
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
return apply(f, (bddp)v, BC_CHANGE, 0);
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
bddp bddintersec(f, g)
|
1125
|
+
bddp f, g;
|
1126
|
+
/* Returns bddnull if not enough memory */
|
1127
|
+
{
|
1128
|
+
struct B_NodeTable *fp;
|
1129
|
+
|
1130
|
+
/* Check operands */
|
1131
|
+
if(f == bddnull) return bddnull;
|
1132
|
+
if(g == bddnull) return bddnull;
|
1133
|
+
if(B_CST(f))
|
1134
|
+
{ if(B_ABS(f) != bddfalse) err("bddintersec: Invalid bddp", f); }
|
1135
|
+
else
|
1136
|
+
{
|
1137
|
+
fp = B_NP(f);
|
1138
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1139
|
+
err("bddintersec: Invalid bddp", f);
|
1140
|
+
if(!B_Z_NP(fp)) err("bddintersec: applying non-ZBDD node", f);
|
1141
|
+
}
|
1142
|
+
if(B_CST(g))
|
1143
|
+
{ if(B_ABS(g) != bddfalse) err("bddintersec: Invalid bddp", g); }
|
1144
|
+
else
|
1145
|
+
{
|
1146
|
+
fp = B_NP(g);
|
1147
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1148
|
+
err("bddintersec: Invalid bddp", g);
|
1149
|
+
if(!B_Z_NP(fp)) err("bddintersec: applying non-ZBDD node", g);
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
return apply(f, g, BC_INTERSEC, 0);
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
bddp bddunion(f, g)
|
1156
|
+
bddp f, g;
|
1157
|
+
/* Returns bddnull if not enough memory */
|
1158
|
+
{
|
1159
|
+
struct B_NodeTable *fp;
|
1160
|
+
|
1161
|
+
/* Check operands */
|
1162
|
+
if(f == bddnull) return bddnull;
|
1163
|
+
if(g == bddnull) return bddnull;
|
1164
|
+
if(B_CST(f))
|
1165
|
+
{ if(B_ABS(f) != bddfalse) err("bddunion: Invalid bddp", f); }
|
1166
|
+
else
|
1167
|
+
{
|
1168
|
+
fp = B_NP(f);
|
1169
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1170
|
+
err("bddunion: Invalid bddp", f);
|
1171
|
+
if(!B_Z_NP(fp)) err("bddunion: applying non-ZBDD node", f);
|
1172
|
+
}
|
1173
|
+
if(B_CST(g))
|
1174
|
+
{ if(B_ABS(g) != bddfalse) err("bddunion: Invalid bddp", g); }
|
1175
|
+
else
|
1176
|
+
{
|
1177
|
+
fp = B_NP(g);
|
1178
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1179
|
+
err("bddunion: Invalid bddp", g);
|
1180
|
+
if(!B_Z_NP(fp)) err("bddunion: applying non-ZBDD node", g);
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
return apply(f, g, BC_UNION, 0);
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
bddp bddsubtract(f, g)
|
1187
|
+
bddp f, g;
|
1188
|
+
/* Returns bddnull if not enough memory */
|
1189
|
+
{
|
1190
|
+
struct B_NodeTable *fp;
|
1191
|
+
|
1192
|
+
/* Check operands */
|
1193
|
+
if(f == bddnull) return bddnull;
|
1194
|
+
if(g == bddnull) return bddnull;
|
1195
|
+
if(B_CST(f))
|
1196
|
+
{ if(B_ABS(f) != bddfalse) err("bddsubtract: Invalid bddp", f); }
|
1197
|
+
else
|
1198
|
+
{
|
1199
|
+
fp = B_NP(f);
|
1200
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1201
|
+
err("bddsubtarct: Invalid bddp", f);
|
1202
|
+
if(!B_Z_NP(fp)) err("bddsubtarct: applying non-ZBDD node", f);
|
1203
|
+
}
|
1204
|
+
if(B_CST(g))
|
1205
|
+
{ if(B_ABS(g) != bddfalse) err("bddsubtarct: Invalid bddp", g); }
|
1206
|
+
else
|
1207
|
+
{
|
1208
|
+
fp = B_NP(g);
|
1209
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1210
|
+
err("bddsubtarct: Invalid bddp", g);
|
1211
|
+
if(!B_Z_NP(fp)) err("bddsubtarct: applying non-ZBDD node", g);
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
return apply(f, g, BC_SUBTRACT, 0);
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
bddp bddcard(f)
|
1218
|
+
bddp f;
|
1219
|
+
{
|
1220
|
+
struct B_NodeTable *fp;
|
1221
|
+
|
1222
|
+
if(f == bddnull) return 0;
|
1223
|
+
if(B_CST(f)) return (f == bddempty)? 0: 1;
|
1224
|
+
fp = B_NP(f);
|
1225
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1226
|
+
err("bddcard: Invalid bddp", f);
|
1227
|
+
if(!B_Z_NP(fp)) err("bddcard: applying non-ZBDD node", f);
|
1228
|
+
|
1229
|
+
return apply(f, bddempty, BC_CARD, 0);
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
bddp bddlit(f)
|
1233
|
+
bddp f;
|
1234
|
+
{
|
1235
|
+
struct B_NodeTable *fp;
|
1236
|
+
|
1237
|
+
if(f == bddnull) return 0;
|
1238
|
+
if(B_CST(f)) return 0;
|
1239
|
+
fp = B_NP(f);
|
1240
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1241
|
+
err("bddlit: Invalid bddp", f);
|
1242
|
+
if(!B_Z_NP(fp)) err("bddlit: applying non-ZBDD node", f);
|
1243
|
+
|
1244
|
+
return apply(f, bddempty, BC_LIT, 0);
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
bddp bddlen(f)
|
1248
|
+
bddp f;
|
1249
|
+
{
|
1250
|
+
struct B_NodeTable *fp;
|
1251
|
+
|
1252
|
+
if(f == bddnull) return 0;
|
1253
|
+
if(B_CST(f)) return 0;
|
1254
|
+
fp = B_NP(f);
|
1255
|
+
if(fp>=Node+NodeSpc || !fp->varrfc)
|
1256
|
+
err("bddlen: Invalid bddp", f);
|
1257
|
+
if(!B_Z_NP(fp)) err("bddlen: applying non-ZBDD node", f);
|
1258
|
+
|
1259
|
+
return apply(f, bddempty, BC_LEN, 0);
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
|
1263
|
+
|
1264
|
+
/* ----------------- Internal functions ------------------ */
|
1265
|
+
static void var_enlarge()
|
1266
|
+
{
|
1267
|
+
bddvar i, newSpc;
|
1268
|
+
struct B_VarTable *newVar;
|
1269
|
+
unsigned int *newVarID;
|
1270
|
+
|
1271
|
+
/* Get new size */
|
1272
|
+
if(VarSpc == bddvarmax+1U)
|
1273
|
+
err("var_enlarge: var index range full", VarSpc);
|
1274
|
+
newSpc = VarSpc << 2U;
|
1275
|
+
if(newSpc > bddvarmax+1) newSpc = bddvarmax+1U;
|
1276
|
+
|
1277
|
+
/* Enlarge space */
|
1278
|
+
newVar = B_MALLOC(struct B_VarTable, newSpc);
|
1279
|
+
newVarID = B_MALLOC(unsigned int, newSpc);
|
1280
|
+
if(newVar && newVarID)
|
1281
|
+
{
|
1282
|
+
for(i=0; i<VarSpc; i++)
|
1283
|
+
{
|
1284
|
+
newVar[i].hashSpc = Var[i].hashSpc;
|
1285
|
+
newVar[i].hashUsed = Var[i].hashUsed;
|
1286
|
+
newVar[i].lev = Var[i].lev;
|
1287
|
+
newVar[i].hash_32 = Var[i].hash_32;
|
1288
|
+
newVarID[i] = VarID[i];
|
1289
|
+
#ifdef B_64
|
1290
|
+
newVar[i].hash_h8 = Var[i].hash_h8;
|
1291
|
+
#endif
|
1292
|
+
}
|
1293
|
+
free(Var);
|
1294
|
+
free(VarID);
|
1295
|
+
Var = newVar;
|
1296
|
+
VarID = newVarID;
|
1297
|
+
}
|
1298
|
+
else
|
1299
|
+
{
|
1300
|
+
if(newVar) free(newVar);
|
1301
|
+
if(newVarID) free(newVarID);
|
1302
|
+
err("var_enlarge: memory allocation failed", VarSpc);
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
/* Initialize new space */
|
1306
|
+
for(i=VarSpc; i<newSpc; i++)
|
1307
|
+
{
|
1308
|
+
Var[i].hashSpc = 0;
|
1309
|
+
Var[i].hashUsed = 0;
|
1310
|
+
Var[i].lev = i;
|
1311
|
+
Var[i].hash_32 = 0;
|
1312
|
+
VarID[i] = i;
|
1313
|
+
#ifdef B_64
|
1314
|
+
Var[i].hash_h8 = 0;
|
1315
|
+
#endif
|
1316
|
+
}
|
1317
|
+
VarSpc = newSpc;
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
static int node_enlarge()
|
1321
|
+
/* Returns 1 if not enough memory */
|
1322
|
+
{
|
1323
|
+
bddp i, newSpc;
|
1324
|
+
struct B_NodeTable *newNode;
|
1325
|
+
struct B_CacheTable *newCache, *cp, *cp1;
|
1326
|
+
|
1327
|
+
/* Get new size */
|
1328
|
+
if(NodeSpc == NodeLimit) return 1; /* Cannot enlarge */
|
1329
|
+
newSpc = NodeSpc << 1U;
|
1330
|
+
if(newSpc > NodeLimit) newSpc = NodeLimit;
|
1331
|
+
|
1332
|
+
/* Enlarge space */
|
1333
|
+
newNode = B_MALLOC(struct B_NodeTable, newSpc);
|
1334
|
+
if(newNode)
|
1335
|
+
{
|
1336
|
+
for(i=0; i<NodeSpc; i++)
|
1337
|
+
{
|
1338
|
+
newNode[i].varrfc = Node[i].varrfc;
|
1339
|
+
newNode[i].f0_32 = Node[i].f0_32;
|
1340
|
+
newNode[i].f1_32 = Node[i].f1_32;
|
1341
|
+
newNode[i].nx_32 = Node[i].nx_32;
|
1342
|
+
#ifdef B_64
|
1343
|
+
newNode[i].f0_h8 = Node[i].f0_h8;
|
1344
|
+
newNode[i].f1_h8 = Node[i].f1_h8;
|
1345
|
+
newNode[i].nx_h8 = Node[i].nx_h8;
|
1346
|
+
#endif /* B_64 */
|
1347
|
+
}
|
1348
|
+
free(Node);
|
1349
|
+
Node = newNode;
|
1350
|
+
}
|
1351
|
+
else return 1; /* Not enough memory */
|
1352
|
+
|
1353
|
+
/* Initialize new space */
|
1354
|
+
Node[newSpc-1U].varrfc = 0;
|
1355
|
+
B_SET_BDDP(Node[newSpc-1U].nx, Avail);
|
1356
|
+
for(i=NodeSpc; i<newSpc-1U; i++)
|
1357
|
+
{
|
1358
|
+
Node[i].varrfc = 0;
|
1359
|
+
B_SET_BDDP(Node[i].nx, i+1U);
|
1360
|
+
}
|
1361
|
+
Avail = NodeSpc;
|
1362
|
+
NodeSpc = newSpc;
|
1363
|
+
|
1364
|
+
/* Realloc Cache */
|
1365
|
+
for(newSpc=CacheSpc; newSpc<NodeSpc>>1U; newSpc<<=1U)
|
1366
|
+
; /* empty */
|
1367
|
+
newCache = B_MALLOC(struct B_CacheTable, newSpc);
|
1368
|
+
if(newCache)
|
1369
|
+
{
|
1370
|
+
for(i=0; i<CacheSpc; i++)
|
1371
|
+
{
|
1372
|
+
cp = newCache + i;
|
1373
|
+
cp1 = Cache + i;
|
1374
|
+
cp->op = cp1->op;
|
1375
|
+
B_CPY_BDDP(cp->f, cp1->f);
|
1376
|
+
B_CPY_BDDP(cp->g, cp1->g);
|
1377
|
+
B_CPY_BDDP(cp->h, cp1->h);
|
1378
|
+
}
|
1379
|
+
free(Cache);
|
1380
|
+
Cache = newCache;
|
1381
|
+
}
|
1382
|
+
else return 0; /* Only NodeTable enlarged */
|
1383
|
+
|
1384
|
+
/* Reconstruct Cache */
|
1385
|
+
for(i=CacheSpc; i<newSpc; i++)
|
1386
|
+
{
|
1387
|
+
cp = Cache + i;
|
1388
|
+
cp1 = Cache + (i & (CacheSpc - 1));
|
1389
|
+
cp->op = cp1->op;
|
1390
|
+
B_CPY_BDDP(cp->f, cp1->f);
|
1391
|
+
B_CPY_BDDP(cp->g, cp1->g);
|
1392
|
+
B_CPY_BDDP(cp->h, cp1->h);
|
1393
|
+
}
|
1394
|
+
CacheSpc = newSpc;
|
1395
|
+
|
1396
|
+
return 0;
|
1397
|
+
}
|
1398
|
+
|
1399
|
+
static int hash_enlarge(v)
|
1400
|
+
bddvar v;
|
1401
|
+
/* Returns 1 if not enough memory */
|
1402
|
+
{
|
1403
|
+
struct B_NodeTable *np, *np0;
|
1404
|
+
struct B_VarTable *varp;
|
1405
|
+
bddp i, oldSpc, newSpc, nx, key, f0, f1;
|
1406
|
+
bddp_32 *newhash_32, *p_32;
|
1407
|
+
#ifdef B_64
|
1408
|
+
bddp_h8 *newhash_h8, *p_h8;
|
1409
|
+
#endif
|
1410
|
+
|
1411
|
+
varp = &Var[v];
|
1412
|
+
/* Get new size */
|
1413
|
+
oldSpc = varp->hashSpc;
|
1414
|
+
if(oldSpc == B_NODE_MAX + 1U)
|
1415
|
+
return 0; /* Cancel enlarging */
|
1416
|
+
newSpc = oldSpc << 1U;
|
1417
|
+
|
1418
|
+
/* Enlarge space */
|
1419
|
+
#ifdef B_64
|
1420
|
+
newhash_32 = B_MALLOC(bddp_32, newSpc);
|
1421
|
+
newhash_h8 = B_MALLOC(bddp_h8, newSpc);
|
1422
|
+
if(newhash_32 && newhash_h8)
|
1423
|
+
{
|
1424
|
+
for(i=0; i<varp->hashSpc; i++)
|
1425
|
+
{
|
1426
|
+
newhash_32[i] = varp->hash_32[i];
|
1427
|
+
newhash_h8[i] = varp->hash_h8[i];
|
1428
|
+
}
|
1429
|
+
free(varp->hash_32);
|
1430
|
+
free(varp->hash_h8);
|
1431
|
+
varp->hash_32 = newhash_32;
|
1432
|
+
varp->hash_h8 = newhash_h8;
|
1433
|
+
}
|
1434
|
+
else
|
1435
|
+
{
|
1436
|
+
if(newhash_32) free(newhash_32);
|
1437
|
+
if(newhash_h8) free(newhash_h8);
|
1438
|
+
return 1;
|
1439
|
+
}
|
1440
|
+
#else
|
1441
|
+
newhash_32 = B_MALLOC(bddp_32, newSpc);
|
1442
|
+
if(newhash_32)
|
1443
|
+
{
|
1444
|
+
for(i=0; i<varp->hashSpc; i++) newhash_32[i] = varp->hash_32[i];
|
1445
|
+
free(varp->hash_32);
|
1446
|
+
varp->hash_32 = newhash_32;
|
1447
|
+
}
|
1448
|
+
else return 1; /* Not enough memory */
|
1449
|
+
#endif
|
1450
|
+
varp->hashSpc = newSpc;
|
1451
|
+
|
1452
|
+
/* Initialize new hash entry */
|
1453
|
+
for(i=oldSpc; i<newSpc; i++)
|
1454
|
+
{
|
1455
|
+
B_SET_NXP(p, varp->hash, i);
|
1456
|
+
B_SET_BDDP(*p, bddnull);
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
/* restore hash entry */
|
1460
|
+
for(i=0; i<oldSpc; i++)
|
1461
|
+
{
|
1462
|
+
np0 = 0;
|
1463
|
+
B_SET_NXP(p, varp->hash, i);
|
1464
|
+
nx = B_GET_BDDP(*p);
|
1465
|
+
while(nx != bddnull)
|
1466
|
+
{
|
1467
|
+
np = Node + nx;
|
1468
|
+
f0 = B_GET_BDDP(np->f0);
|
1469
|
+
f1 = B_GET_BDDP(np->f1);
|
1470
|
+
key = B_HASHKEY(f0, f1, newSpc);
|
1471
|
+
if(key == i) np0 = np;
|
1472
|
+
else
|
1473
|
+
{
|
1474
|
+
if(np0) B_CPY_BDDP(np0->nx, np->nx);
|
1475
|
+
else { B_SET_NXP(p, varp->hash, i); B_CPY_BDDP(*p, np->nx); }
|
1476
|
+
B_SET_NXP(p, varp->hash, key);
|
1477
|
+
B_CPY_BDDP(np->nx, *p);
|
1478
|
+
B_SET_BDDP(*p, nx);
|
1479
|
+
}
|
1480
|
+
if(np0) nx = B_GET_BDDP(np0->nx);
|
1481
|
+
else { B_SET_NXP(p, varp->hash, i); nx = B_GET_BDDP(*p); }
|
1482
|
+
}
|
1483
|
+
}
|
1484
|
+
return 0;
|
1485
|
+
}
|
1486
|
+
|
1487
|
+
static bddp getnode(v, f0, f1)
|
1488
|
+
bddvar v;
|
1489
|
+
bddp f0, f1;
|
1490
|
+
/* Returns bddnull if not enough memory */
|
1491
|
+
{
|
1492
|
+
/* After checking elimination rule & negative edge rule */
|
1493
|
+
struct B_NodeTable *np, *fp;
|
1494
|
+
struct B_VarTable *varp;
|
1495
|
+
bddp ix, nx, key;
|
1496
|
+
bddp_32 *p_32;
|
1497
|
+
#ifdef B_64
|
1498
|
+
bddp_h8 *p_h8;
|
1499
|
+
#endif
|
1500
|
+
|
1501
|
+
varp = &Var[v];
|
1502
|
+
if(varp->hashSpc == 0)
|
1503
|
+
/* Create hash-table */
|
1504
|
+
{
|
1505
|
+
varp->hash_32 = B_MALLOC(bddp_32, B_HASH_SPC0);
|
1506
|
+
if(!varp->hash_32) return bddnull;
|
1507
|
+
#ifdef B_64
|
1508
|
+
varp->hash_h8 = B_MALLOC(bddp_h8, B_HASH_SPC0);
|
1509
|
+
if(!varp->hash_h8)
|
1510
|
+
{
|
1511
|
+
free(varp->hash_32);
|
1512
|
+
return bddnull;
|
1513
|
+
}
|
1514
|
+
#endif
|
1515
|
+
for(ix=0; ix<B_HASH_SPC0; ix++)
|
1516
|
+
{
|
1517
|
+
B_SET_NXP(p, varp->hash, ix);
|
1518
|
+
B_SET_BDDP(*p, bddnull);
|
1519
|
+
}
|
1520
|
+
varp->hashSpc = B_HASH_SPC0;
|
1521
|
+
key = B_HASHKEY(f0, f1, varp->hashSpc);
|
1522
|
+
}
|
1523
|
+
else
|
1524
|
+
/* Looking for equivalent existing node */
|
1525
|
+
{
|
1526
|
+
key = B_HASHKEY(f0, f1, varp->hashSpc);
|
1527
|
+
B_SET_NXP(p, varp->hash, key);
|
1528
|
+
nx = B_GET_BDDP(*p);
|
1529
|
+
while(nx != bddnull)
|
1530
|
+
{
|
1531
|
+
np = Node + nx;
|
1532
|
+
if(f0 == B_GET_BDDP(np->f0) &&
|
1533
|
+
f1 == B_GET_BDDP(np->f1) )
|
1534
|
+
{
|
1535
|
+
/* Sharing equivalent node */
|
1536
|
+
if(!B_CST(f0)) { fp = B_NP(f0); B_RFC_DEC_NP(fp); }
|
1537
|
+
if(!B_CST(f1)) { fp = B_NP(f1); B_RFC_DEC_NP(fp); }
|
1538
|
+
B_RFC_INC_NP(np);
|
1539
|
+
return B_BDDP_NP(np);
|
1540
|
+
}
|
1541
|
+
nx = B_GET_BDDP(np->nx);
|
1542
|
+
}
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
/* Check hash-table overflow */
|
1546
|
+
if(++ varp->hashUsed >= varp->hashSpc)
|
1547
|
+
{
|
1548
|
+
if(hash_enlarge(v)) return bddnull; /* Hash-table overflow */
|
1549
|
+
key = B_HASHKEY(f0, f1, varp->hashSpc); /* Enlarge success */
|
1550
|
+
}
|
1551
|
+
|
1552
|
+
/* Check node-table overflow */
|
1553
|
+
if(NodeUsed >= NodeSpc-1U)
|
1554
|
+
{
|
1555
|
+
if(node_enlarge())
|
1556
|
+
{
|
1557
|
+
if(bddgc()) return bddnull; /* Node-table overflow */
|
1558
|
+
key = B_HASHKEY(f0, f1, varp->hashSpc);
|
1559
|
+
}
|
1560
|
+
/* Node-table enlarged or GC succeeded */
|
1561
|
+
}
|
1562
|
+
NodeUsed++;
|
1563
|
+
|
1564
|
+
/* Creating a new node */
|
1565
|
+
nx = Avail;
|
1566
|
+
np = Node + nx;
|
1567
|
+
Avail = B_GET_BDDP(np->nx);
|
1568
|
+
B_SET_NXP(p, varp->hash, key);
|
1569
|
+
B_CPY_BDDP(np->nx, *p);
|
1570
|
+
B_SET_BDDP(*p, nx);
|
1571
|
+
B_SET_BDDP(np->f0, f0);
|
1572
|
+
B_SET_BDDP(np->f1, f1);
|
1573
|
+
np->varrfc = v;
|
1574
|
+
B_RFC_INC_NP(np);
|
1575
|
+
return B_BDDP_NP(np);
|
1576
|
+
}
|
1577
|
+
|
1578
|
+
static bddp getbddp(v, f0, f1)
|
1579
|
+
bddvar v;
|
1580
|
+
bddp f0, f1;
|
1581
|
+
/* Returns bddnull if not enough memory */
|
1582
|
+
{
|
1583
|
+
struct B_NodeTable *fp;
|
1584
|
+
|
1585
|
+
/* Check elimination rule */
|
1586
|
+
if(f0 == f1)
|
1587
|
+
{
|
1588
|
+
if(!B_CST(f0)) { fp = B_NP(f0); B_RFC_DEC_NP(fp); }
|
1589
|
+
return f0;
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
/* Negative edge constraint */
|
1593
|
+
if(B_NEG(f0))
|
1594
|
+
{
|
1595
|
+
bddp h;
|
1596
|
+
|
1597
|
+
h = getnode(v, B_NOT(f0), B_NOT(f1));
|
1598
|
+
if(h == bddnull) return bddnull;
|
1599
|
+
return B_NOT(h);
|
1600
|
+
}
|
1601
|
+
return getnode(v, f0, f1);
|
1602
|
+
}
|
1603
|
+
|
1604
|
+
static bddp apply(f, g, op, skip)
|
1605
|
+
bddp f, g;
|
1606
|
+
unsigned char op, skip;
|
1607
|
+
/* Returns bddnull if not enough memory */
|
1608
|
+
{
|
1609
|
+
struct B_NodeTable *fp, *gp;
|
1610
|
+
struct B_CacheTable *cachep;
|
1611
|
+
bddp key, f0, f1, g0, g1, h0, h1, h;
|
1612
|
+
bddvar v, flev, glev;
|
1613
|
+
char z; /* flag to check ZBDD node */
|
1614
|
+
|
1615
|
+
/* Check terminal case */
|
1616
|
+
if(!skip) switch(op)
|
1617
|
+
{
|
1618
|
+
case BC_AND:
|
1619
|
+
/* Check trivial cases */
|
1620
|
+
if(f == bddfalse || g == bddfalse || f == B_NOT(g))
|
1621
|
+
return bddfalse;
|
1622
|
+
if(f == g)
|
1623
|
+
{
|
1624
|
+
if(f != bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); }
|
1625
|
+
return f;
|
1626
|
+
}
|
1627
|
+
if(f == bddtrue) { fp = B_NP(g); B_RFC_INC_NP(fp); return g; }
|
1628
|
+
if(g == bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1629
|
+
/* Check operand swap */
|
1630
|
+
if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
|
1631
|
+
break;
|
1632
|
+
|
1633
|
+
case BC_XOR:
|
1634
|
+
/* Check trivial cases */
|
1635
|
+
if(f == g) return bddfalse;
|
1636
|
+
if(f == B_NOT(g)) return bddtrue;
|
1637
|
+
if(f == bddfalse) { fp = B_NP(g); B_RFC_INC_NP(fp); return g; }
|
1638
|
+
if(g == bddfalse) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1639
|
+
if(f == bddtrue) {fp=B_NP(g); B_RFC_INC_NP(fp); return B_NOT(g);}
|
1640
|
+
if(g == bddtrue) {fp=B_NP(f); B_RFC_INC_NP(fp); return B_NOT(f);}
|
1641
|
+
/* Check negation */
|
1642
|
+
if(B_NEG(f) && B_NEG(g)) { f = B_NOT(f); g = B_NOT(g); }
|
1643
|
+
else if(B_NEG(f) || B_NEG(g))
|
1644
|
+
{
|
1645
|
+
f = B_ABS(f); g = B_ABS(g);
|
1646
|
+
/* Check operand swap */
|
1647
|
+
h = (f < g)? apply(g, f, op, 1): apply(f, g, op, 1);
|
1648
|
+
if(h == bddnull) return bddnull;
|
1649
|
+
return B_NOT(h);
|
1650
|
+
}
|
1651
|
+
/* Check operand swap */
|
1652
|
+
if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
|
1653
|
+
break;
|
1654
|
+
|
1655
|
+
case BC_COFACTOR:
|
1656
|
+
/* Check trivial cases */
|
1657
|
+
if(B_CST(f)) return f;
|
1658
|
+
if(g == bddfalse || f == B_NOT(g)) return bddfalse;
|
1659
|
+
if(f == g) return bddtrue;
|
1660
|
+
if(g == bddtrue) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1661
|
+
break;
|
1662
|
+
|
1663
|
+
case BC_UNIV:
|
1664
|
+
/* Check trivial cases */
|
1665
|
+
if(B_CST(f)) return f;
|
1666
|
+
if(B_CST(g)) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1667
|
+
if(B_NEG(g)) g = B_NOT(g);
|
1668
|
+
break;
|
1669
|
+
|
1670
|
+
case BC_SUPPORT:
|
1671
|
+
if(B_CST(f)) return bddfalse;
|
1672
|
+
if(B_NEG(f)) f = B_NOT(f);
|
1673
|
+
break;
|
1674
|
+
|
1675
|
+
case BC_INTERSEC:
|
1676
|
+
/* Check trivial cases */
|
1677
|
+
if(f == bddfalse || g == bddfalse) return bddfalse;
|
1678
|
+
if(f == bddtrue) return B_NEG(g)? bddtrue: bddfalse;
|
1679
|
+
if(g == bddtrue) return B_NEG(f)? bddtrue: bddfalse;
|
1680
|
+
if(f == g) { fp = B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1681
|
+
if(f == B_NOT(g)) {fp=B_NP(f); B_RFC_INC_NP(fp); return B_ABS(f); }
|
1682
|
+
/* Check operand swap */
|
1683
|
+
if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
|
1684
|
+
break;
|
1685
|
+
|
1686
|
+
case BC_UNION:
|
1687
|
+
/* Check trivial cases */
|
1688
|
+
if(f == bddfalse)
|
1689
|
+
{
|
1690
|
+
if(!B_CST(g)) {fp=B_NP(g); B_RFC_INC_NP(fp); }
|
1691
|
+
return g;
|
1692
|
+
}
|
1693
|
+
if(f == bddtrue)
|
1694
|
+
{
|
1695
|
+
if(!B_CST(g)) {fp=B_NP(g); B_RFC_INC_NP(fp); }
|
1696
|
+
return B_NEG(g)? g: B_NOT(g);
|
1697
|
+
}
|
1698
|
+
if(g == bddfalse || f == g)
|
1699
|
+
{ fp=B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1700
|
+
if(g == bddtrue || f == B_NOT(g))
|
1701
|
+
{
|
1702
|
+
fp=B_NP(f); B_RFC_INC_NP(fp);
|
1703
|
+
return B_NEG(f)? f: B_NOT(f);
|
1704
|
+
}
|
1705
|
+
/* Check operand swap */
|
1706
|
+
if(f < g) { h = f; f = g; g = h; } /* swap (f, g) */
|
1707
|
+
break;
|
1708
|
+
|
1709
|
+
case BC_SUBTRACT:
|
1710
|
+
/* Check trivial cases */
|
1711
|
+
if(f == bddfalse || f == g) return bddfalse;
|
1712
|
+
if(f == bddtrue || f == B_NOT(g))
|
1713
|
+
return B_NEG(g)? bddfalse: bddtrue;
|
1714
|
+
if(g == bddfalse) { fp=B_NP(f); B_RFC_INC_NP(fp); return f; }
|
1715
|
+
if(g == bddtrue) { fp=B_NP(f); B_RFC_INC_NP(fp); return B_ABS(f); }
|
1716
|
+
break;
|
1717
|
+
|
1718
|
+
case BC_AT0:
|
1719
|
+
case BC_AT1:
|
1720
|
+
case BC_OFFSET:
|
1721
|
+
/* Check trivial cases */
|
1722
|
+
if(B_CST(f)) return f;
|
1723
|
+
/* special cases */
|
1724
|
+
fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
|
1725
|
+
glev = Var[(bddvar)g].lev;
|
1726
|
+
if(flev < glev) { B_RFC_INC_NP(fp); return f; }
|
1727
|
+
if(flev == glev)
|
1728
|
+
{
|
1729
|
+
if(op != BC_AT1)
|
1730
|
+
{
|
1731
|
+
h = B_GET_BDDP(fp->f0);
|
1732
|
+
if(B_NEG(f)^B_NEG(h)) h = B_NOT(h);
|
1733
|
+
}
|
1734
|
+
else
|
1735
|
+
{
|
1736
|
+
h = B_GET_BDDP(fp->f1);
|
1737
|
+
if(B_NEG(f)) h = B_NOT(h);
|
1738
|
+
}
|
1739
|
+
if(!B_CST(h)) { fp = B_NP(h); B_RFC_INC_NP(fp); }
|
1740
|
+
return h;
|
1741
|
+
}
|
1742
|
+
/* Check negation */
|
1743
|
+
if(B_NEG(f))
|
1744
|
+
{
|
1745
|
+
h = apply(B_NOT(f), g, op, 1);
|
1746
|
+
if(h == bddnull) return bddnull;
|
1747
|
+
return B_NOT(h);
|
1748
|
+
}
|
1749
|
+
break;
|
1750
|
+
|
1751
|
+
case BC_ONSET:
|
1752
|
+
/* Check trivial cases */
|
1753
|
+
if(B_CST(f)) return bddfalse;
|
1754
|
+
/* special cases */
|
1755
|
+
fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
|
1756
|
+
glev = Var[(bddvar)g].lev;
|
1757
|
+
if(flev < glev) return bddfalse;
|
1758
|
+
if(flev == glev)
|
1759
|
+
{
|
1760
|
+
h = B_GET_BDDP(fp->f1);
|
1761
|
+
if(!B_CST(h)) { fp = B_NP(h); B_RFC_INC_NP(fp); }
|
1762
|
+
return h;
|
1763
|
+
}
|
1764
|
+
/* Check negation */
|
1765
|
+
if(B_NEG(f)) f = B_NOT(f);
|
1766
|
+
break;
|
1767
|
+
|
1768
|
+
case BC_CHANGE:
|
1769
|
+
/* Check trivial cases */
|
1770
|
+
if(f == bddfalse) return f;
|
1771
|
+
if(B_CST(f)) return getzbddp((bddvar)g, bddfalse, f);
|
1772
|
+
/* special cases */
|
1773
|
+
fp = B_NP(f); flev = Var[B_VAR_NP(fp)].lev;
|
1774
|
+
glev = Var[(bddvar)g].lev;
|
1775
|
+
if(flev < glev)
|
1776
|
+
{
|
1777
|
+
B_RFC_INC_NP(fp);
|
1778
|
+
h = getzbddp((bddvar)g, bddfalse, f);
|
1779
|
+
if(h == bddnull) bddfree(f);
|
1780
|
+
return h;
|
1781
|
+
}
|
1782
|
+
if(flev == glev)
|
1783
|
+
{
|
1784
|
+
h0 = B_GET_BDDP(fp->f1);
|
1785
|
+
h1 = B_GET_BDDP(fp->f0);
|
1786
|
+
if(B_NEG(f)^B_NEG(h1)) h1 = B_NOT(h1);
|
1787
|
+
if(!B_CST(h0)) { fp = B_NP(h0); B_RFC_INC_NP(fp); }
|
1788
|
+
if(!B_CST(h1)) { fp = B_NP(h1); B_RFC_INC_NP(fp); }
|
1789
|
+
h = getzbddp((bddvar)g, h0, h1);
|
1790
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); }
|
1791
|
+
return h;
|
1792
|
+
}
|
1793
|
+
break;
|
1794
|
+
|
1795
|
+
case BC_LSHIFT:
|
1796
|
+
case BC_RSHIFT:
|
1797
|
+
/* Check trivial cases */
|
1798
|
+
if(B_CST(f)) return f;
|
1799
|
+
|
1800
|
+
/* Check negation */
|
1801
|
+
if(B_NEG(f))
|
1802
|
+
{
|
1803
|
+
h = apply(B_NOT(f), g, op, 1);
|
1804
|
+
if(h == bddnull) return bddnull;
|
1805
|
+
return B_NOT(h);
|
1806
|
+
}
|
1807
|
+
break;
|
1808
|
+
|
1809
|
+
case BC_CARD:
|
1810
|
+
if(B_CST(f)) return (f == bddempty)? 0: 1;
|
1811
|
+
if(B_NEG(f)) return apply(B_NOT(f), bddempty, op, 1) + 1;
|
1812
|
+
break;
|
1813
|
+
|
1814
|
+
case BC_LIT:
|
1815
|
+
if(B_CST(f)) return 0;
|
1816
|
+
if(B_NEG(f)) f = B_NOT(f);
|
1817
|
+
break;
|
1818
|
+
|
1819
|
+
case BC_LEN:
|
1820
|
+
if(B_CST(f)) return 0;
|
1821
|
+
if(B_NEG(f)) f = B_NOT(f);
|
1822
|
+
break;
|
1823
|
+
|
1824
|
+
default:
|
1825
|
+
err("apply: unknown opcode", op);
|
1826
|
+
break;
|
1827
|
+
}
|
1828
|
+
|
1829
|
+
/* Non-trivial operations */
|
1830
|
+
switch(op)
|
1831
|
+
{
|
1832
|
+
/* binary operation */
|
1833
|
+
case BC_AND:
|
1834
|
+
case BC_XOR:
|
1835
|
+
case BC_COFACTOR:
|
1836
|
+
case BC_UNIV:
|
1837
|
+
case BC_INTERSEC:
|
1838
|
+
case BC_UNION:
|
1839
|
+
case BC_SUBTRACT:
|
1840
|
+
/* Try cache? */
|
1841
|
+
if((B_CST(f) || B_RFC_ONE_NP(B_NP(f))) &&
|
1842
|
+
(B_CST(g) || B_RFC_ONE_NP(B_NP(g)))) key = bddnull;
|
1843
|
+
else
|
1844
|
+
{
|
1845
|
+
/* Checking Cache */
|
1846
|
+
key = B_CACHEKEY(op, f, g);
|
1847
|
+
cachep = Cache + key;
|
1848
|
+
if(cachep->op == op &&
|
1849
|
+
f == B_GET_BDDP(cachep->f) &&
|
1850
|
+
g == B_GET_BDDP(cachep->g))
|
1851
|
+
{
|
1852
|
+
/* Hit */
|
1853
|
+
h = B_GET_BDDP(cachep->h);
|
1854
|
+
if(!B_CST(h) && h != bddnull) { fp = B_NP(h); B_RFC_INC_NP(fp); }
|
1855
|
+
return h;
|
1856
|
+
}
|
1857
|
+
}
|
1858
|
+
/* Get (f0, f1) and (g0, g1)*/
|
1859
|
+
z = 0;
|
1860
|
+
fp = B_NP(f);
|
1861
|
+
flev = B_CST(f)? 0: Var[B_VAR_NP(fp)].lev;
|
1862
|
+
gp = B_NP(g);
|
1863
|
+
glev = B_CST(g)? 0: Var[B_VAR_NP(gp)].lev;
|
1864
|
+
f0 = f; f1 = f;
|
1865
|
+
g0 = g; g1 = g;
|
1866
|
+
|
1867
|
+
if(flev <= glev)
|
1868
|
+
{
|
1869
|
+
v = B_VAR_NP(gp);
|
1870
|
+
if(B_Z_NP(gp))
|
1871
|
+
{
|
1872
|
+
z = 1;
|
1873
|
+
if(flev < glev) f1 = bddfalse;
|
1874
|
+
}
|
1875
|
+
g0 = B_GET_BDDP(gp->f0);
|
1876
|
+
g1 = B_GET_BDDP(gp->f1);
|
1877
|
+
if(B_NEG(g)^B_NEG(g0)) g0 = B_NOT(g0);
|
1878
|
+
if(B_NEG(g) && !z) g1 = B_NOT(g1);
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
if(flev >= glev)
|
1882
|
+
{
|
1883
|
+
v = B_VAR_NP(fp);
|
1884
|
+
if(B_Z_NP(fp))
|
1885
|
+
{
|
1886
|
+
z = 1;
|
1887
|
+
if(flev > glev) g1 = bddfalse;
|
1888
|
+
}
|
1889
|
+
f0 = B_GET_BDDP(fp->f0);
|
1890
|
+
f1 = B_GET_BDDP(fp->f1);
|
1891
|
+
if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
|
1892
|
+
if(B_NEG(f) && !z) f1 = B_NOT(f1);
|
1893
|
+
}
|
1894
|
+
break;
|
1895
|
+
|
1896
|
+
/* unary operation */
|
1897
|
+
case BC_AT0:
|
1898
|
+
case BC_AT1:
|
1899
|
+
case BC_LSHIFT:
|
1900
|
+
case BC_RSHIFT:
|
1901
|
+
case BC_SUPPORT:
|
1902
|
+
case BC_OFFSET:
|
1903
|
+
case BC_ONSET:
|
1904
|
+
case BC_CHANGE:
|
1905
|
+
fp = B_NP(f);
|
1906
|
+
if(B_RFC_ONE_NP(fp)) key = bddnull;
|
1907
|
+
else
|
1908
|
+
{
|
1909
|
+
/* Checking Cache */
|
1910
|
+
key = B_CACHEKEY(op, f, g);
|
1911
|
+
cachep = Cache + key;
|
1912
|
+
if(cachep->op == op &&
|
1913
|
+
f == B_GET_BDDP(cachep->f) &&
|
1914
|
+
g == B_GET_BDDP(cachep->g))
|
1915
|
+
{
|
1916
|
+
/* Hit */
|
1917
|
+
h = B_GET_BDDP(cachep->h);
|
1918
|
+
if(!B_CST(h) && h != bddnull) { fp = B_NP(h); B_RFC_INC_NP(fp); }
|
1919
|
+
return h;
|
1920
|
+
}
|
1921
|
+
}
|
1922
|
+
/* Get (f0, f1)*/
|
1923
|
+
v = B_VAR_NP(fp);
|
1924
|
+
z = B_Z_NP(fp)? 1: 0;
|
1925
|
+
f0 = B_GET_BDDP(fp->f0);
|
1926
|
+
f1 = B_GET_BDDP(fp->f1);
|
1927
|
+
if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
|
1928
|
+
if(B_NEG(f) && !z) f1 = B_NOT(f1);
|
1929
|
+
break;
|
1930
|
+
|
1931
|
+
case BC_CARD:
|
1932
|
+
case BC_LIT:
|
1933
|
+
case BC_LEN:
|
1934
|
+
fp = B_NP(f);
|
1935
|
+
if(B_RFC_ONE_NP(fp)) key = bddnull;
|
1936
|
+
else
|
1937
|
+
{
|
1938
|
+
/* Checking Cache */
|
1939
|
+
key = B_CACHEKEY(op, f, bddempty);
|
1940
|
+
cachep = Cache + key;
|
1941
|
+
if(cachep->op == op &&
|
1942
|
+
f == B_GET_BDDP(cachep->f) &&
|
1943
|
+
bddempty == B_GET_BDDP(cachep->g))
|
1944
|
+
{
|
1945
|
+
/* Hit */
|
1946
|
+
return B_GET_BDDP(cachep->h);
|
1947
|
+
}
|
1948
|
+
}
|
1949
|
+
/* Get (f0, f1)*/
|
1950
|
+
f0 = B_GET_BDDP(fp->f0);
|
1951
|
+
f1 = B_GET_BDDP(fp->f1);
|
1952
|
+
if(B_NEG(f)^B_NEG(f0)) f0 = B_NOT(f0);
|
1953
|
+
break;
|
1954
|
+
|
1955
|
+
default:
|
1956
|
+
err("apply: unknown opcode", op);
|
1957
|
+
}
|
1958
|
+
|
1959
|
+
/* Stack overflow limitter */
|
1960
|
+
BDD_RECUR_INC;
|
1961
|
+
|
1962
|
+
/* Get result node */
|
1963
|
+
switch(op)
|
1964
|
+
{
|
1965
|
+
case BC_AND:
|
1966
|
+
case BC_XOR:
|
1967
|
+
case BC_INTERSEC:
|
1968
|
+
case BC_UNION:
|
1969
|
+
case BC_SUBTRACT:
|
1970
|
+
h0 = apply(f0, g0, op, 0);
|
1971
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
1972
|
+
h1 = apply(f1, g1, op, 0);
|
1973
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
1974
|
+
h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
|
1975
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
|
1976
|
+
break;
|
1977
|
+
|
1978
|
+
case BC_COFACTOR:
|
1979
|
+
if(g0 == bddfalse && g1 != bddfalse)
|
1980
|
+
{
|
1981
|
+
h = apply(f1, g1, op, 0);
|
1982
|
+
}
|
1983
|
+
else if(g1 == bddfalse && g0 != bddfalse)
|
1984
|
+
{
|
1985
|
+
h = apply(f0, g0, op, 0);
|
1986
|
+
}
|
1987
|
+
else
|
1988
|
+
{
|
1989
|
+
h0 = apply(f0, g0, op, 0);
|
1990
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
1991
|
+
h1 = apply(f1, g1, op, 0);
|
1992
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
1993
|
+
h = getbddp(v, h0, h1);
|
1994
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
|
1995
|
+
}
|
1996
|
+
break;
|
1997
|
+
|
1998
|
+
case BC_UNIV:
|
1999
|
+
if(g0 != g1)
|
2000
|
+
{
|
2001
|
+
h0 = apply(f0, g0, op, 0);
|
2002
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
2003
|
+
h1 = apply(f1, g0, op, 0);
|
2004
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
2005
|
+
h = apply(h0, h1, BC_AND, 0);
|
2006
|
+
bddfree(h0); bddfree(h1);
|
2007
|
+
}
|
2008
|
+
else
|
2009
|
+
{
|
2010
|
+
h0 = apply(f0, g0, op, 0);
|
2011
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
2012
|
+
h1 = apply(f1, g0, op, 0);
|
2013
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
2014
|
+
h = getbddp(v, h0, h1);
|
2015
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
|
2016
|
+
}
|
2017
|
+
break;
|
2018
|
+
|
2019
|
+
case BC_AT0:
|
2020
|
+
case BC_AT1:
|
2021
|
+
case BC_OFFSET:
|
2022
|
+
case BC_ONSET:
|
2023
|
+
case BC_CHANGE:
|
2024
|
+
h0 = apply(f0, g, op, 0);
|
2025
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
2026
|
+
h1 = apply(f1, g, op, 0);
|
2027
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
2028
|
+
h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
|
2029
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
|
2030
|
+
break;
|
2031
|
+
|
2032
|
+
case BC_SUPPORT:
|
2033
|
+
h0 = apply(f0, bddfalse, op, 0);
|
2034
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
2035
|
+
h1 = apply(f1, bddfalse, op, 0);
|
2036
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
2037
|
+
h = z? apply(h0, h1, BC_UNION, 0):
|
2038
|
+
apply(B_NOT(h0), B_NOT(h1), BC_AND, 0);
|
2039
|
+
bddfree(h0); bddfree(h1);
|
2040
|
+
if(h == bddnull) break; /* Overflow */
|
2041
|
+
h0 = h;
|
2042
|
+
h = z? getzbddp(v, h0, bddtrue):
|
2043
|
+
getbddp(v, B_NOT(h0), bddtrue);
|
2044
|
+
if(h == bddnull) bddfree(h0); /* Overflow */
|
2045
|
+
break;
|
2046
|
+
|
2047
|
+
case BC_LSHIFT:
|
2048
|
+
case BC_RSHIFT:
|
2049
|
+
/* Get VarID of new level */
|
2050
|
+
{
|
2051
|
+
bddvar flev, newlev;
|
2052
|
+
|
2053
|
+
flev = bddlevofvar(v);
|
2054
|
+
if(op == BC_LSHIFT)
|
2055
|
+
{
|
2056
|
+
newlev = flev + (bddvar)g;
|
2057
|
+
if(newlev > VarUsed || newlev < flev)
|
2058
|
+
err("apply: Invald shift", newlev);
|
2059
|
+
}
|
2060
|
+
else
|
2061
|
+
{
|
2062
|
+
newlev = flev - (bddvar)g;
|
2063
|
+
if(newlev == 0 || newlev > flev)
|
2064
|
+
err("apply: Invald shift", newlev);
|
2065
|
+
}
|
2066
|
+
v = bddvaroflev(newlev);
|
2067
|
+
}
|
2068
|
+
h0 = apply(f0, g, op, 0);
|
2069
|
+
if(h0 == bddnull) { h = h0; break; } /* Overflow */
|
2070
|
+
h1 = apply(f1, g, op, 0);
|
2071
|
+
if(h1 == bddnull) { bddfree(h0); h = h1; break; } /* Overflow */
|
2072
|
+
h = z? getzbddp(v, h0, h1): getbddp(v, h0, h1);
|
2073
|
+
if(h == bddnull) { bddfree(h0); bddfree(h1); } /* Overflow */
|
2074
|
+
break;
|
2075
|
+
|
2076
|
+
case BC_CARD:
|
2077
|
+
h = apply(f0, bddempty, op, 0)
|
2078
|
+
+ apply(f1, bddempty, op, 0);
|
2079
|
+
if(h >= bddnull) h = bddnull - 1;
|
2080
|
+
break;
|
2081
|
+
|
2082
|
+
case BC_LIT:
|
2083
|
+
h = apply(f0, bddempty, op, 0)
|
2084
|
+
+ apply(f1, bddempty, op, 0);
|
2085
|
+
if(h >= bddnull) h = bddnull - 1;
|
2086
|
+
h += apply(f1, bddempty, BC_CARD, 0);
|
2087
|
+
if(h >= bddnull) h = bddnull - 1;
|
2088
|
+
break;
|
2089
|
+
|
2090
|
+
case BC_LEN:
|
2091
|
+
h0 = apply(f0, bddempty, op, 0);
|
2092
|
+
h1 = apply(f1, bddempty, op, 0) + 1;
|
2093
|
+
h = (h0 < h1)? h1: h0;
|
2094
|
+
break;
|
2095
|
+
|
2096
|
+
default:
|
2097
|
+
err("apply: unknown opcode", op);
|
2098
|
+
break;
|
2099
|
+
}
|
2100
|
+
|
2101
|
+
/* Stack overflow limitter */
|
2102
|
+
BDD_RECUR_DEC;
|
2103
|
+
|
2104
|
+
/* Saving to Cache */
|
2105
|
+
if(key != bddnull && h != bddnull)
|
2106
|
+
{
|
2107
|
+
cachep = Cache + key;
|
2108
|
+
cachep->op = op;
|
2109
|
+
B_SET_BDDP(cachep->f, f);
|
2110
|
+
B_SET_BDDP(cachep->g, g);
|
2111
|
+
B_SET_BDDP(cachep->h, h);
|
2112
|
+
if(h == f) switch(op)
|
2113
|
+
{
|
2114
|
+
case BC_AT0:
|
2115
|
+
key = B_CACHEKEY(BC_AT1, f, g);
|
2116
|
+
cachep = Cache + key;
|
2117
|
+
cachep->op = BC_AT1;
|
2118
|
+
B_SET_BDDP(cachep->f, f);
|
2119
|
+
B_SET_BDDP(cachep->g, g);
|
2120
|
+
B_SET_BDDP(cachep->h, h);
|
2121
|
+
break;
|
2122
|
+
case BC_AT1:
|
2123
|
+
key = B_CACHEKEY(BC_AT0, f, g);
|
2124
|
+
cachep = Cache + key;
|
2125
|
+
cachep->op = BC_AT0;
|
2126
|
+
B_SET_BDDP(cachep->f, f);
|
2127
|
+
B_SET_BDDP(cachep->g, g);
|
2128
|
+
B_SET_BDDP(cachep->h, h);
|
2129
|
+
break;
|
2130
|
+
case BC_OFFSET:
|
2131
|
+
key = B_CACHEKEY(BC_ONSET, f, g);
|
2132
|
+
cachep = Cache + key;
|
2133
|
+
cachep->op = BC_ONSET;
|
2134
|
+
B_SET_BDDP(cachep->f, f);
|
2135
|
+
B_SET_BDDP(cachep->g, g);
|
2136
|
+
B_SET_BDDP(cachep->h, bddfalse);
|
2137
|
+
break;
|
2138
|
+
default:
|
2139
|
+
break;
|
2140
|
+
}
|
2141
|
+
if(h == bddfalse && op == BC_ONSET)
|
2142
|
+
{
|
2143
|
+
key = B_CACHEKEY(BC_OFFSET, f, g);
|
2144
|
+
cachep = Cache + key;
|
2145
|
+
cachep->op = BC_OFFSET;
|
2146
|
+
B_SET_BDDP(cachep->f, f);
|
2147
|
+
B_SET_BDDP(cachep->g, g);
|
2148
|
+
B_SET_BDDP(cachep->h, f);
|
2149
|
+
}
|
2150
|
+
}
|
2151
|
+
return h;
|
2152
|
+
}
|
2153
|
+
|
2154
|
+
static void gc1(np)
|
2155
|
+
struct B_NodeTable *np;
|
2156
|
+
{
|
2157
|
+
/* np is a node ptr to be collected. (refc == 0) */
|
2158
|
+
bddp key, nx1, f0, f1;
|
2159
|
+
struct B_VarTable *varp;
|
2160
|
+
struct B_NodeTable *np1, *np2;
|
2161
|
+
bddp_32 *p_32;
|
2162
|
+
#ifdef B_64
|
2163
|
+
bddp_h8 *p_h8;
|
2164
|
+
#endif
|
2165
|
+
|
2166
|
+
/* remove the node from hash list */
|
2167
|
+
varp = Var + B_VAR_NP(np);
|
2168
|
+
f0 = B_GET_BDDP(np->f0);
|
2169
|
+
f1 = B_GET_BDDP(np->f1);
|
2170
|
+
key = B_HASHKEY(f0, f1, varp->hashSpc);
|
2171
|
+
B_SET_NXP(p, varp->hash, key);
|
2172
|
+
nx1 = B_GET_BDDP(*p);
|
2173
|
+
np1 = Node + nx1;
|
2174
|
+
|
2175
|
+
if(np1 == np) B_CPY_BDDP(*p, np->nx);
|
2176
|
+
else
|
2177
|
+
{
|
2178
|
+
while(np1 != np)
|
2179
|
+
{
|
2180
|
+
if(nx1 == bddnull)
|
2181
|
+
err("gc1: Fail to find the node to be deleted", np-Node);
|
2182
|
+
np2 = np1;
|
2183
|
+
nx1 = B_GET_BDDP(np2->nx);
|
2184
|
+
np1 = Node + nx1;
|
2185
|
+
}
|
2186
|
+
B_CPY_BDDP(np2->nx, np->nx);
|
2187
|
+
}
|
2188
|
+
varp->hashUsed--;
|
2189
|
+
|
2190
|
+
/* append the node to avail list */
|
2191
|
+
B_SET_BDDP(np->nx, Avail);
|
2192
|
+
Avail = np - Node;
|
2193
|
+
|
2194
|
+
NodeUsed--;
|
2195
|
+
np->varrfc = 0;
|
2196
|
+
|
2197
|
+
/* Check sub-graphs recursively */
|
2198
|
+
if(!B_CST(f0))
|
2199
|
+
{
|
2200
|
+
np1 = B_NP(f0);
|
2201
|
+
B_RFC_DEC_NP(np1);
|
2202
|
+
if(B_RFC_ZERO_NP(np1))
|
2203
|
+
{ BDD_RECUR_INC; gc1(np1); BDD_RECUR_DEC; }
|
2204
|
+
}
|
2205
|
+
if(!B_CST(f1))
|
2206
|
+
{
|
2207
|
+
np1 = B_NP(f1);
|
2208
|
+
B_RFC_DEC_NP(np1);
|
2209
|
+
if(B_RFC_ZERO_NP(np1))
|
2210
|
+
{ BDD_RECUR_INC; gc1(np1); BDD_RECUR_DEC; }
|
2211
|
+
}
|
2212
|
+
}
|
2213
|
+
|
2214
|
+
static bddp count(f)
|
2215
|
+
bddp f;
|
2216
|
+
{
|
2217
|
+
bddp nx;
|
2218
|
+
bddp c, g;
|
2219
|
+
bddvar flev, glev;
|
2220
|
+
struct B_NodeTable *fp;
|
2221
|
+
struct B_NodeTable *gp;
|
2222
|
+
|
2223
|
+
/* Check consistensy
|
2224
|
+
if(f == bddnull)
|
2225
|
+
err("count: bddnull found", bddnull);
|
2226
|
+
*/
|
2227
|
+
|
2228
|
+
if(B_CST(f)) return 0; /* Constant */
|
2229
|
+
fp = B_NP(f);
|
2230
|
+
|
2231
|
+
/* Check visit flag */
|
2232
|
+
nx = B_GET_BDDP(fp->nx);
|
2233
|
+
if(nx & B_CST_MASK) return 0;
|
2234
|
+
|
2235
|
+
/* Check consistensy
|
2236
|
+
flev = Var[B_VAR_NP(fp)].lev;
|
2237
|
+
g = B_GET_BDDP(fp->f0);
|
2238
|
+
if(!B_CST(g))
|
2239
|
+
{
|
2240
|
+
gp = B_NP(g); glev = Var[B_VAR_NP(gp)].lev;
|
2241
|
+
if(flev <= glev)
|
2242
|
+
err("count: inconsistensy found at f0", fp-Node);
|
2243
|
+
}
|
2244
|
+
g = B_GET_BDDP(fp->f1);
|
2245
|
+
if(!B_CST(g))
|
2246
|
+
{
|
2247
|
+
gp = B_NP(g); glev = Var[B_VAR_NP(gp)].lev;
|
2248
|
+
if(flev <= glev)
|
2249
|
+
err("count: inconsistensy found at f1", fp-Node);
|
2250
|
+
}
|
2251
|
+
*/
|
2252
|
+
|
2253
|
+
BDD_RECUR_INC;
|
2254
|
+
c = count(B_GET_BDDP(fp->f0)) + count(B_GET_BDDP(fp->f1)) + 1U ;
|
2255
|
+
BDD_RECUR_DEC;
|
2256
|
+
|
2257
|
+
/* Set visit flag */
|
2258
|
+
B_SET_BDDP(fp->nx, nx | B_CST_MASK);
|
2259
|
+
|
2260
|
+
return c;
|
2261
|
+
}
|
2262
|
+
|
2263
|
+
static void export(strm, f)
|
2264
|
+
FILE *strm;
|
2265
|
+
bddp f;
|
2266
|
+
{
|
2267
|
+
bddp nx, f0, f1;
|
2268
|
+
bddvar v;
|
2269
|
+
struct B_NodeTable *fp;
|
2270
|
+
|
2271
|
+
if(B_CST(f)) return; /* Constant */
|
2272
|
+
fp = B_NP(f);
|
2273
|
+
|
2274
|
+
/* Check visit flag */
|
2275
|
+
nx = B_GET_BDDP(fp->nx);
|
2276
|
+
if(nx & B_CST_MASK) return;
|
2277
|
+
|
2278
|
+
/* Set visit flag */
|
2279
|
+
B_SET_BDDP(fp->nx, nx | B_CST_MASK);
|
2280
|
+
|
2281
|
+
/* Dump its subgraphs recursively */
|
2282
|
+
v = B_VAR_NP(fp);
|
2283
|
+
f0 = B_GET_BDDP(fp->f0);
|
2284
|
+
f0 = B_ABS(f0);
|
2285
|
+
f1 = B_GET_BDDP(fp->f1);
|
2286
|
+
BDD_RECUR_INC;
|
2287
|
+
export(strm, f0);
|
2288
|
+
export(strm, f1);
|
2289
|
+
BDD_RECUR_DEC;
|
2290
|
+
|
2291
|
+
/* Dump this node */
|
2292
|
+
fprintf(strm, B_BDDP_FD, B_ABS(f));
|
2293
|
+
fprintf(strm, " %d ", Var[v].lev);
|
2294
|
+
if(f0 == bddfalse) fprintf(strm, "F");
|
2295
|
+
else if(f0 == bddtrue) fprintf(strm, "T");
|
2296
|
+
else fprintf(strm, B_BDDP_FD, f0);
|
2297
|
+
fprintf(strm, " ");
|
2298
|
+
if(f1 == bddfalse) fprintf(strm, "F");
|
2299
|
+
else if(f1 == bddtrue) fprintf(strm, "T");
|
2300
|
+
else fprintf(strm, B_BDDP_FD, f1);
|
2301
|
+
fprintf(strm, "\n");
|
2302
|
+
}
|
2303
|
+
|
2304
|
+
static void dump(f)
|
2305
|
+
bddp f;
|
2306
|
+
{
|
2307
|
+
bddp nx, f0, f1;
|
2308
|
+
bddvar v;
|
2309
|
+
struct B_NodeTable *fp;
|
2310
|
+
|
2311
|
+
if(B_CST(f)) return; /* Constant */
|
2312
|
+
fp = B_NP(f);
|
2313
|
+
|
2314
|
+
/* Check visit flag */
|
2315
|
+
nx = B_GET_BDDP(fp->nx);
|
2316
|
+
if(nx & B_CST_MASK) return;
|
2317
|
+
|
2318
|
+
/* Set visit flag */
|
2319
|
+
B_SET_BDDP(fp->nx, nx | B_CST_MASK);
|
2320
|
+
|
2321
|
+
/* Dump its subgraphs recursively */
|
2322
|
+
v = B_VAR_NP(fp);
|
2323
|
+
f0 = B_GET_BDDP(fp->f0);
|
2324
|
+
f0 = B_ABS(f0);
|
2325
|
+
f1 = B_GET_BDDP(fp->f1);
|
2326
|
+
BDD_RECUR_INC;
|
2327
|
+
dump(f0);
|
2328
|
+
dump(f1);
|
2329
|
+
BDD_RECUR_DEC;
|
2330
|
+
|
2331
|
+
/* Dump this node */
|
2332
|
+
printf("N");
|
2333
|
+
printf(B_BDDP_FD, B_NDX(f));
|
2334
|
+
printf(" = [V%d(%d), ", v, Var[v].lev);
|
2335
|
+
if(B_CST(f0)) printf(B_BDDP_FD, B_VAL(f0));
|
2336
|
+
else { printf("N"); printf(B_BDDP_FD, B_NDX(f0)); }
|
2337
|
+
printf(", ");
|
2338
|
+
if(B_NEG(f1)) putchar('~');
|
2339
|
+
if(B_CST(f1)) printf(B_BDDP_FD, B_ABS(B_VAL(f1)));
|
2340
|
+
else { printf("N"); printf(B_BDDP_FD, B_NDX(f1)); }
|
2341
|
+
printf("]");
|
2342
|
+
if(B_Z_NP(fp)) printf(" #Z");
|
2343
|
+
printf("\n");
|
2344
|
+
}
|
2345
|
+
|
2346
|
+
static void reset(f)
|
2347
|
+
bddp f;
|
2348
|
+
{
|
2349
|
+
bddp nx;
|
2350
|
+
struct B_NodeTable *fp;
|
2351
|
+
|
2352
|
+
if(B_CST(f)) return; /* Constant */
|
2353
|
+
fp = B_NP(f);
|
2354
|
+
|
2355
|
+
/* Check visit flag */
|
2356
|
+
nx = B_GET_BDDP(fp->nx);
|
2357
|
+
if(nx & B_CST_MASK)
|
2358
|
+
{
|
2359
|
+
/* Reset visit flag */
|
2360
|
+
B_SET_BDDP(fp->nx, nx & ~B_CST_MASK);
|
2361
|
+
BDD_RECUR_INC;
|
2362
|
+
reset(B_GET_BDDP(fp->f0));
|
2363
|
+
reset(B_GET_BDDP(fp->f1));
|
2364
|
+
BDD_RECUR_DEC;
|
2365
|
+
}
|
2366
|
+
}
|
2367
|
+
|
2368
|
+
static bddp getzbddp(v, f0, f1)
|
2369
|
+
bddvar v;
|
2370
|
+
bddp f0, f1;
|
2371
|
+
/* Returns bddnull if not enough memory */
|
2372
|
+
{
|
2373
|
+
struct B_NodeTable *fp;
|
2374
|
+
|
2375
|
+
/* Check elimination rule */
|
2376
|
+
if(f1 == bddfalse) return f0;
|
2377
|
+
|
2378
|
+
/* Negative edge constraint */
|
2379
|
+
if(B_NEG(f0))
|
2380
|
+
{
|
2381
|
+
bddp h;
|
2382
|
+
|
2383
|
+
h = getnode(v, f0, f1);
|
2384
|
+
if(h == bddnull) return bddnull;
|
2385
|
+
return B_NOT(h);
|
2386
|
+
}
|
2387
|
+
return getnode(v, B_NOT(f0), f1);
|
2388
|
+
}
|
2389
|
+
|
2390
|
+
static int andfalse(f, g)
|
2391
|
+
bddp f, g;
|
2392
|
+
{
|
2393
|
+
struct B_NodeTable *fp, *gp;
|
2394
|
+
struct B_CacheTable *cachep;
|
2395
|
+
bddp key, f0, f1, g0, g1, h0, h1, h;
|
2396
|
+
bddvar v, flev, glev;
|
2397
|
+
|
2398
|
+
/* Check trivial cases */
|
2399
|
+
if(f == bddfalse || g == bddfalse || f == B_NOT(g)) return 0;
|
2400
|
+
if(f == bddtrue || g == bddtrue || f == g) return 1;
|
2401
|
+
/* Check operand swap */
|
2402
|
+
if(f > g) { h = f; f = g; g = h; } /* swap (f, g) */
|
2403
|
+
|
2404
|
+
/* Non-trivial operations */
|
2405
|
+
/* Try cache? */
|
2406
|
+
if((B_CST(f) || B_RFC_ONE_NP(B_NP(f))) &&
|
2407
|
+
(B_CST(g) || B_RFC_ONE_NP(B_NP(g)))) key = bddnull;
|
2408
|
+
else
|
2409
|
+
{
|
2410
|
+
/* Checking Cache */
|
2411
|
+
key = B_CACHEKEY(BC_AND, f, g);
|
2412
|
+
cachep = Cache + key;
|
2413
|
+
if(cachep->op == BC_AND &&
|
2414
|
+
f == B_GET_BDDP(cachep->f) &&
|
2415
|
+
g == B_GET_BDDP(cachep->g))
|
2416
|
+
{
|
2417
|
+
/* Hit */
|
2418
|
+
h = B_GET_BDDP(cachep->h);
|
2419
|
+
return (h==bddfalse)? 0: 1;
|
2420
|
+
}
|
2421
|
+
}
|
2422
|
+
/* Get (f0, f1) and (g0, g1)*/
|
2423
|
+
fp = B_NP(f);
|
2424
|
+
flev = B_CST(f)? 0: Var[B_VAR_NP(fp)].lev;
|
2425
|
+
gp = B_NP(g);
|
2426
|
+
glev = B_CST(g)? 0: Var[B_VAR_NP(gp)].lev;
|
2427
|
+
f0 = f; f1 = f;
|
2428
|
+
g0 = g; g1 = g;
|
2429
|
+
|
2430
|
+
if(flev <= glev)
|
2431
|
+
{
|
2432
|
+
v = B_VAR_NP(gp);
|
2433
|
+
g0 = B_GET_BDDP(gp->f0);
|
2434
|
+
g1 = B_GET_BDDP(gp->f1);
|
2435
|
+
if(B_NEG(g)) { g0 = B_NOT(g0); g1 = B_NOT(g1); }
|
2436
|
+
}
|
2437
|
+
|
2438
|
+
if(flev >= glev)
|
2439
|
+
{
|
2440
|
+
v = B_VAR_NP(fp);
|
2441
|
+
f0 = B_GET_BDDP(fp->f0);
|
2442
|
+
f1 = B_GET_BDDP(fp->f1);
|
2443
|
+
if(B_NEG(f)) { f0 = B_NOT(f0); f1 = B_NOT(f1); }
|
2444
|
+
}
|
2445
|
+
|
2446
|
+
/* Get result */
|
2447
|
+
if(andfalse(f0, g0) == 1) return 1;
|
2448
|
+
if(andfalse(f1, g1) == 1) return 1;
|
2449
|
+
|
2450
|
+
/* Saving to Cache */
|
2451
|
+
if(key != bddnull)
|
2452
|
+
{
|
2453
|
+
cachep = Cache + key;
|
2454
|
+
cachep->op = BC_AND;
|
2455
|
+
B_SET_BDDP(cachep->f, f);
|
2456
|
+
B_SET_BDDP(cachep->g, g);
|
2457
|
+
B_SET_BDDP(cachep->h, bddfalse);
|
2458
|
+
}
|
2459
|
+
return 0;
|
2460
|
+
}
|
2461
|
+
|
2462
|
+
static int err(msg, num)
|
2463
|
+
char *msg;
|
2464
|
+
bddp num;
|
2465
|
+
{
|
2466
|
+
fprintf(stderr,"***** ERROR %s ( ", msg);
|
2467
|
+
fprintf(stderr, B_BDDP_FX, num);
|
2468
|
+
fprintf(stderr," ) *****\n");
|
2469
|
+
fprintf(stderr," NodeLimit : ");
|
2470
|
+
fprintf(stderr, B_BDDP_FD, NodeLimit);
|
2471
|
+
fprintf(stderr,"\t NodeSpc : ");
|
2472
|
+
fprintf(stderr, B_BDDP_FD, NodeSpc);
|
2473
|
+
fprintf(stderr,"\t VarSpc : %d",VarSpc);
|
2474
|
+
fprintf(stderr,"\n CacheSpc : ");
|
2475
|
+
fprintf(stderr, B_BDDP_FD, CacheSpc);
|
2476
|
+
fprintf(stderr,"\t NodeUsed : ");
|
2477
|
+
fprintf(stderr, B_BDDP_FD, NodeUsed);
|
2478
|
+
fprintf(stderr,"\t VarUsed : %d\n",VarUsed);
|
2479
|
+
exit(1);
|
2480
|
+
return 1;
|
2481
|
+
}
|
2482
|
+
|
2483
|
+
static int rfc_inc_ovf(np)
|
2484
|
+
struct B_NodeTable *np;
|
2485
|
+
{
|
2486
|
+
bddp ix, nx, nx2, key, rfc, oldSpc;
|
2487
|
+
bddp *p, *p2;
|
2488
|
+
struct B_RFC_Table *oldRFCT;
|
2489
|
+
|
2490
|
+
/* printf("rfc_inc %d (u:%d)\n", np-Node, RFCT_Used); */
|
2491
|
+
if(RFCT_Spc == 0)
|
2492
|
+
{
|
2493
|
+
/* Create RFC-table */
|
2494
|
+
RFCT = B_MALLOC(struct B_RFC_Table, B_RFCT_SPC0);
|
2495
|
+
if(!RFCT)
|
2496
|
+
{
|
2497
|
+
err("B_RFC_INC_NP: rfc memory over flow", np-Node);
|
2498
|
+
return 1;
|
2499
|
+
}
|
2500
|
+
for(ix=0; ix<B_RFCT_SPC0; ix++)
|
2501
|
+
{
|
2502
|
+
B_SET_BDDP((RFCT+ix)->nx, bddnull);
|
2503
|
+
B_SET_BDDP((RFCT+ix)->rfc, (bddp)0);
|
2504
|
+
}
|
2505
|
+
RFCT_Spc = B_RFCT_SPC0;
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
nx = np - Node;
|
2509
|
+
key = nx & (RFCT_Spc-1);
|
2510
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2511
|
+
while(nx2 != bddnull)
|
2512
|
+
{
|
2513
|
+
if(nx == nx2)
|
2514
|
+
{
|
2515
|
+
if(np->varrfc < B_RFC_MASK)
|
2516
|
+
{
|
2517
|
+
rfc = 0;
|
2518
|
+
np->varrfc += B_RFC_UNIT;
|
2519
|
+
}
|
2520
|
+
else rfc = B_GET_BDDP((RFCT+key)->rfc) + 1;
|
2521
|
+
B_SET_BDDP((RFCT+key)->rfc, rfc);
|
2522
|
+
return 0;
|
2523
|
+
}
|
2524
|
+
key = (key+1) & (RFCT_Spc-1);
|
2525
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2526
|
+
}
|
2527
|
+
|
2528
|
+
/* new rfc entry */
|
2529
|
+
B_SET_BDDP((RFCT+key)->nx, nx);
|
2530
|
+
B_SET_BDDP((RFCT+key)->rfc, (bddp)0);
|
2531
|
+
np->varrfc += B_RFC_UNIT;
|
2532
|
+
RFCT_Used++;
|
2533
|
+
|
2534
|
+
if((RFCT_Used << 1) >= RFCT_Spc)
|
2535
|
+
{
|
2536
|
+
/* Enlarge RFC-table */
|
2537
|
+
oldSpc = RFCT_Spc;
|
2538
|
+
RFCT_Spc <<= 2;
|
2539
|
+
|
2540
|
+
oldRFCT = RFCT;
|
2541
|
+
RFCT = B_MALLOC(struct B_RFC_Table, RFCT_Spc);
|
2542
|
+
if(!RFCT)
|
2543
|
+
{
|
2544
|
+
err("B_RFC_INC_NP: rfc memory over flow", np-Node);
|
2545
|
+
return 1;
|
2546
|
+
}
|
2547
|
+
for(ix=0; ix<RFCT_Spc; ix++)
|
2548
|
+
{
|
2549
|
+
B_SET_BDDP((RFCT+ix)->nx, bddnull);
|
2550
|
+
B_SET_BDDP((RFCT+ix)->rfc, (bddp)0);
|
2551
|
+
}
|
2552
|
+
for(ix=0; ix<oldSpc; ix++)
|
2553
|
+
{
|
2554
|
+
nx = B_GET_BDDP((oldRFCT+ix)->nx);
|
2555
|
+
if(nx == bddnull) continue;
|
2556
|
+
key = nx & (RFCT_Spc-1);
|
2557
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2558
|
+
while(nx2 != bddnull)
|
2559
|
+
{
|
2560
|
+
key = (key+1) & (RFCT_Spc-1);
|
2561
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2562
|
+
}
|
2563
|
+
B_SET_BDDP((RFCT+key)->nx, nx);
|
2564
|
+
rfc = B_GET_BDDP((oldRFCT+ix)->rfc);
|
2565
|
+
B_SET_BDDP((RFCT+key)->rfc, rfc);
|
2566
|
+
}
|
2567
|
+
free(oldRFCT);
|
2568
|
+
}
|
2569
|
+
|
2570
|
+
return 0;
|
2571
|
+
}
|
2572
|
+
|
2573
|
+
static int rfc_dec_ovf(np)
|
2574
|
+
struct B_NodeTable *np;
|
2575
|
+
{
|
2576
|
+
bddp nx, key, nx2, rfc;
|
2577
|
+
|
2578
|
+
/* printf("rfc_dec %d (u:%d)\n", np-Node, RFCT_Used); */
|
2579
|
+
nx = np - Node;
|
2580
|
+
key = nx & (RFCT_Spc-1);
|
2581
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2582
|
+
while(nx2 != bddnull)
|
2583
|
+
{
|
2584
|
+
if(nx == nx2)
|
2585
|
+
{
|
2586
|
+
rfc = B_GET_BDDP((RFCT+key)->rfc);
|
2587
|
+
if(rfc == 0)
|
2588
|
+
{
|
2589
|
+
np->varrfc -= B_RFC_UNIT;
|
2590
|
+
return 0;
|
2591
|
+
}
|
2592
|
+
B_SET_BDDP((RFCT+key)->rfc, rfc-1);
|
2593
|
+
return 0;
|
2594
|
+
}
|
2595
|
+
key = (key+1) & (RFCT_Spc-1);
|
2596
|
+
nx2 = B_GET_BDDP((RFCT+key)->nx);
|
2597
|
+
}
|
2598
|
+
return 0;
|
2599
|
+
}
|
2600
|
+
|
2601
|
+
#define IMPORTHASH(x) ((((x)>>1)^((x)<<8)^((x)<<16)) & (hashsize-1))
|
2602
|
+
|
2603
|
+
int import(strm, p, lim, z)
|
2604
|
+
FILE *strm;
|
2605
|
+
bddp *p;
|
2606
|
+
int lim;
|
2607
|
+
int z;
|
2608
|
+
{
|
2609
|
+
int n, m, v, i, lev, var, inv, e;
|
2610
|
+
bddp n_nd, ix, f, f0, f1, nd, nd0, nd1, hashsize, ixx;
|
2611
|
+
char s[256];
|
2612
|
+
bddp *hash1;
|
2613
|
+
bddp *hash2;
|
2614
|
+
|
2615
|
+
v = fscanf(strm, "%s", s);
|
2616
|
+
if(v == EOF) return 1;
|
2617
|
+
if(strcmp(s, "_i") != 0) return 1;
|
2618
|
+
v = fscanf(strm, "%s", s);
|
2619
|
+
if(v == EOF) return 1;
|
2620
|
+
n = strtol(s, NULL, 10);
|
2621
|
+
while(n > bddvarused()) bddnewvar();
|
2622
|
+
|
2623
|
+
v = fscanf(strm, "%s", s);
|
2624
|
+
if(v == EOF) return 1;
|
2625
|
+
if(strcmp(s, "_o") != 0) return 1;
|
2626
|
+
v = fscanf(strm, "%s", s);
|
2627
|
+
if(v == EOF) return 1;
|
2628
|
+
m = strtol(s, NULL, 10);
|
2629
|
+
|
2630
|
+
v = fscanf(strm, "%s", s);
|
2631
|
+
if(v == EOF) return 1;
|
2632
|
+
if(strcmp(s, "_n") != 0) return 1;
|
2633
|
+
v = fscanf(strm, "%s", s);
|
2634
|
+
if(v == EOF) return 1;
|
2635
|
+
n_nd = B_STRTOI(s, NULL, 10);
|
2636
|
+
|
2637
|
+
for(hashsize = 1; hashsize < (n_nd<<1); hashsize <<= 1)
|
2638
|
+
; /* empty */
|
2639
|
+
hash1 = B_MALLOC(bddp, hashsize);
|
2640
|
+
if(hash1 == 0) return 1;
|
2641
|
+
hash2 = B_MALLOC(bddp, hashsize);
|
2642
|
+
if(hash2 == 0)
|
2643
|
+
{
|
2644
|
+
free(hash1);
|
2645
|
+
return 1;
|
2646
|
+
}
|
2647
|
+
for(ix=0; ix<hashsize; ix++) hash1[ix] = bddnull;
|
2648
|
+
|
2649
|
+
e = 0;
|
2650
|
+
for(ix=0; ix<n_nd; ix++)
|
2651
|
+
{
|
2652
|
+
v = fscanf(strm, "%s", s);
|
2653
|
+
if(v == EOF) { e = 1; break; }
|
2654
|
+
nd = B_STRTOI(s, NULL, 10);
|
2655
|
+
|
2656
|
+
v = fscanf(strm, "%s", s);
|
2657
|
+
if(v == EOF) { e = 1; break; }
|
2658
|
+
lev = strtol(s, NULL, 10);
|
2659
|
+
var = bddvaroflev(lev);
|
2660
|
+
|
2661
|
+
v = fscanf(strm, "%s", s);
|
2662
|
+
if(v == EOF) { e = 1; break; }
|
2663
|
+
if(strcmp(s, "F") == 0) f0 = bddfalse;
|
2664
|
+
else if(strcmp(s, "T") == 0) f0 = bddtrue;
|
2665
|
+
else
|
2666
|
+
{
|
2667
|
+
nd0 = B_STRTOI(s, NULL, 10);
|
2668
|
+
|
2669
|
+
ixx = IMPORTHASH(nd0);
|
2670
|
+
while(hash1[ixx] != nd0)
|
2671
|
+
{
|
2672
|
+
if(hash1[ixx] == bddnull)
|
2673
|
+
{
|
2674
|
+
err("bddimport: internal error", ixx);
|
2675
|
+
return 1;
|
2676
|
+
}
|
2677
|
+
ixx++;
|
2678
|
+
ixx &= (hashsize-1);
|
2679
|
+
}
|
2680
|
+
f0 = bddcopy(hash2[ixx]);
|
2681
|
+
}
|
2682
|
+
|
2683
|
+
v = fscanf(strm, "%s", s);
|
2684
|
+
if(v == EOF) { e = 1; bddfree(f0); break; }
|
2685
|
+
if(strcmp(s, "F") == 0) f1 = bddfalse;
|
2686
|
+
else if(strcmp(s, "T") == 0) f1 = bddtrue;
|
2687
|
+
else
|
2688
|
+
{
|
2689
|
+
nd1 = B_STRTOI(s, NULL, 10);
|
2690
|
+
if(nd1 & 1) { inv = 1; nd1 ^= 1; }
|
2691
|
+
else inv = 0;
|
2692
|
+
|
2693
|
+
ixx = IMPORTHASH(nd1);
|
2694
|
+
while(hash1[ixx] != nd1)
|
2695
|
+
{
|
2696
|
+
if(hash1[ixx] == bddnull)
|
2697
|
+
{
|
2698
|
+
err("bddimport: internal error", ixx);
|
2699
|
+
return 1;
|
2700
|
+
}
|
2701
|
+
ixx++;
|
2702
|
+
ixx &= (hashsize-1);
|
2703
|
+
}
|
2704
|
+
f1 = (inv)? bddnot(hash2[ixx]): bddcopy(hash2[ixx]);
|
2705
|
+
}
|
2706
|
+
|
2707
|
+
f = (z)? getzbddp(var, f0, f1): getbddp(var, f0, f1);
|
2708
|
+
if(f == bddnull)
|
2709
|
+
{
|
2710
|
+
e = 1;
|
2711
|
+
bddfree(f1);
|
2712
|
+
bddfree(f0);
|
2713
|
+
break;
|
2714
|
+
}
|
2715
|
+
|
2716
|
+
ixx = IMPORTHASH(nd);
|
2717
|
+
while(hash1[ixx] != bddnull)
|
2718
|
+
{
|
2719
|
+
if(hash1[ixx] == nd)
|
2720
|
+
{
|
2721
|
+
err("bddimport: internal error", ixx);
|
2722
|
+
return 1;
|
2723
|
+
}
|
2724
|
+
ixx++;
|
2725
|
+
ixx &= (hashsize-1);
|
2726
|
+
}
|
2727
|
+
hash1[ixx] = nd;
|
2728
|
+
hash2[ixx] = f;
|
2729
|
+
}
|
2730
|
+
|
2731
|
+
if(e)
|
2732
|
+
{
|
2733
|
+
for(ix=0; ix<hashsize; ix++)
|
2734
|
+
if(hash1[ix] != bddnull) bddfree(hash2[ix]);
|
2735
|
+
free(hash2);
|
2736
|
+
free(hash1);
|
2737
|
+
return 1;
|
2738
|
+
}
|
2739
|
+
|
2740
|
+
for(i=0; i<m; i++)
|
2741
|
+
{
|
2742
|
+
if(i >= lim) break;
|
2743
|
+
v = fscanf(strm, "%s", s);
|
2744
|
+
if(v == EOF)
|
2745
|
+
{
|
2746
|
+
for(i--; i>=0; i--) bddfree(p[i]);
|
2747
|
+
for(ix=0; ix<hashsize; ix++)
|
2748
|
+
if(hash1[ix] != bddnull) bddfree(hash2[ix]);
|
2749
|
+
free(hash2);
|
2750
|
+
free(hash1);
|
2751
|
+
return 1;
|
2752
|
+
}
|
2753
|
+
nd = B_STRTOI(s, NULL, 10);
|
2754
|
+
if(strcmp(s, "F") == 0) p[i] = bddfalse;
|
2755
|
+
else if(strcmp(s, "T") == 0) p[i] = bddtrue;
|
2756
|
+
else
|
2757
|
+
{
|
2758
|
+
if(nd & 1) { inv = 1; nd ^= 1; }
|
2759
|
+
else inv = 0;
|
2760
|
+
|
2761
|
+
ixx = IMPORTHASH(nd);
|
2762
|
+
while(hash1[ixx] != nd)
|
2763
|
+
{
|
2764
|
+
if(hash1[ixx] == bddnull)
|
2765
|
+
{
|
2766
|
+
err("bddimport: internal error", ixx);
|
2767
|
+
return 1;
|
2768
|
+
}
|
2769
|
+
ixx++;
|
2770
|
+
ixx &= (hashsize-1);
|
2771
|
+
}
|
2772
|
+
p[i] = (inv)? bddnot(hash2[ixx]): bddcopy(hash2[ixx]);
|
2773
|
+
}
|
2774
|
+
}
|
2775
|
+
if(i < lim) p[i] = bddnull;
|
2776
|
+
|
2777
|
+
/* clear hash table */
|
2778
|
+
for(ix=0; ix<hashsize; ix++)
|
2779
|
+
if(hash1[ix] != bddnull) bddfree(hash2[ix]);
|
2780
|
+
free(hash2);
|
2781
|
+
free(hash1);
|
2782
|
+
|
2783
|
+
return 0;
|
2784
|
+
}
|
2785
|
+
|
2786
|
+
int bddimport(strm, p, lim)
|
2787
|
+
FILE *strm;
|
2788
|
+
bddp *p;
|
2789
|
+
int lim;
|
2790
|
+
{
|
2791
|
+
return import(strm, p, lim, 0);
|
2792
|
+
}
|
2793
|
+
|
2794
|
+
int bddimportz(strm, p, lim)
|
2795
|
+
FILE *strm;
|
2796
|
+
bddp *p;
|
2797
|
+
int lim;
|
2798
|
+
{
|
2799
|
+
return import(strm, p, lim, 1);
|
2800
|
+
}
|
2801
|
+
|
2802
|
+
bddp bddpush(f, v)
|
2803
|
+
bddp f;
|
2804
|
+
bddvar v;
|
2805
|
+
/* Returns bddnull if not enough memory */
|
2806
|
+
{
|
2807
|
+
struct B_NodeTable *fp;
|
2808
|
+
|
2809
|
+
/* Check operands */
|
2810
|
+
if(v > VarUsed || v == 0) err("bddpush: Invalid VarID", v);
|
2811
|
+
if(f == bddnull) return bddnull;
|
2812
|
+
|
2813
|
+
if(!B_CST(f)) { fp = B_NP(f); B_RFC_INC_NP(fp); }
|
2814
|
+
return getzbddp(v, bddfalse, f);
|
2815
|
+
}
|
2816
|
+
|