Add ABC and ACE2, fix bugs for fpga_flow and VPR
This commit is contained in:
parent
b9d583519b
commit
fe13168f8f
|
@ -0,0 +1,193 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [libSupport.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [The main package.]
|
||||
|
||||
Synopsis [Support for external libaries.]
|
||||
|
||||
Author [Mike Case]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "mainInt.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define MAX_LIBS 256
|
||||
static void* libHandles[MAX_LIBS+1]; // will be null terminated
|
||||
|
||||
typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This will find all the ABC library extensions in the current directory and load them all.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void open_libs() {
|
||||
int curr_lib = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
// printf("Warning: open_libs WIN32 not implemented.\n");
|
||||
#else
|
||||
DIR* dirp;
|
||||
struct dirent* dp;
|
||||
char *env, *init_p, *p;
|
||||
int done;
|
||||
|
||||
env = getenv ("ABC_LIB_PATH");
|
||||
if (env == NULL) {
|
||||
// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n");
|
||||
init_p = malloc (2*sizeof(char));
|
||||
init_p[0]='.'; init_p[1] = 0;
|
||||
} else {
|
||||
init_p = malloc ((strlen(env)+1)*sizeof(char));
|
||||
strcpy (init_p, env);
|
||||
}
|
||||
|
||||
// Extract directories and read libraries
|
||||
done = 0;
|
||||
p = init_p;
|
||||
while (!done) {
|
||||
char *endp = strchr (p,':');
|
||||
if (endp == NULL) done = 1; // last directory in the list
|
||||
else *endp = 0; // end of string
|
||||
|
||||
dirp = opendir(p);
|
||||
if (dirp == NULL) {
|
||||
// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if ((strncmp("libabc_", dp->d_name, 7) == 0) &&
|
||||
(strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) {
|
||||
|
||||
// make sure we don't overflow the handle array
|
||||
if (curr_lib >= MAX_LIBS) {
|
||||
printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n",
|
||||
MAX_LIBS,
|
||||
dp->d_name);
|
||||
}
|
||||
|
||||
// attempt to load it
|
||||
else {
|
||||
char* szPrefixed = malloc((strlen(dp->d_name) + strlen(p) + 2) *
|
||||
sizeof(char));
|
||||
sprintf(szPrefixed, "%s/", p);
|
||||
strcat(szPrefixed, dp->d_name);
|
||||
libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW);
|
||||
|
||||
// did the load succeed?
|
||||
if (libHandles[curr_lib] != 0) {
|
||||
printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib);
|
||||
curr_lib++;
|
||||
} else {
|
||||
printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror());
|
||||
}
|
||||
|
||||
free(szPrefixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
p = endp+1;
|
||||
}
|
||||
|
||||
free(init_p);
|
||||
#endif
|
||||
|
||||
// null terminate the list of handles
|
||||
libHandles[curr_lib] = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This will close all open ABC library extensions
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void close_libs() {
|
||||
#ifdef WIN32
|
||||
printf("Warning: close_libs WIN32 not implemented.\n");
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; libHandles[i] != 0; i++) {
|
||||
if (dlclose(libHandles[i]) != 0) {
|
||||
printf("Warning: failed to close library %d\n", i);
|
||||
}
|
||||
libHandles[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This will get a pointer to a function inside of an open library
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void* get_fnct_ptr(int lib_num, char* sym_name) {
|
||||
#ifdef WIN32
|
||||
printf("Warning: get_fnct_ptr WIN32 not implemented.\n");
|
||||
return 0;
|
||||
#else
|
||||
return dlsym(libHandles[lib_num], sym_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This will call an initialization function in every open library.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void call_inits(Abc_Frame_t* pAbc) {
|
||||
int i;
|
||||
lib_init_end_func init_func;
|
||||
for (i = 0; libHandles[i] != 0; i++) {
|
||||
init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init");
|
||||
if (init_func == 0) {
|
||||
printf("Warning: Failed to initialize library %d.\n", i);
|
||||
} else {
|
||||
(*init_func)(pAbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This will call a shutdown function in every open library.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void call_ends(Abc_Frame_t* pAbc) {
|
||||
int i;
|
||||
lib_init_end_func end_func;
|
||||
for (i = 0; libHandles[i] != 0; i++) {
|
||||
end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end");
|
||||
if (end_func == 0) {
|
||||
printf("Warning: Failed to end library %d.\n", i);
|
||||
} else {
|
||||
(*end_func)(pAbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Libs_Init(Abc_Frame_t * pAbc)
|
||||
{
|
||||
open_libs();
|
||||
call_inits(pAbc);
|
||||
}
|
||||
|
||||
void Libs_End(Abc_Frame_t * pAbc)
|
||||
{
|
||||
call_ends(pAbc);
|
||||
|
||||
// It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind.
|
||||
// close_libs();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,8 @@
|
|||
read JAMIESON_TESTS/ava.blif;
|
||||
resyn2;
|
||||
read_lut JAMIESON_TESTS/lut_lib4.txt;
|
||||
fpga;
|
||||
cec;
|
||||
write_hie JAMIESON_TESTS/ava.blif JAMIESON_TESTS/ava.4.blif;
|
||||
|
||||
time
|
|
@ -0,0 +1,17 @@
|
|||
read JAMIESON_TESTS/mini_example1.blif;
|
||||
resyn2;
|
||||
resyn2rs;
|
||||
read_lut JAMIESON_TESTS/lut_lib4.txt;
|
||||
fpga;
|
||||
cec;
|
||||
write_hie JAMIESON_TESTS/mini_example1.blif JAMIESON_TESTS/mini_example1.4.blif
|
||||
|
||||
read JAMIESON_TESTS/mini_example2.blif;
|
||||
resyn2;
|
||||
resyn2rs;
|
||||
read_lut JAMIESON_TESTS/lut_lib4.txt;
|
||||
fpga;
|
||||
cec;
|
||||
write_hie JAMIESON_TESTS/mini_example2.blif JAMIESON_TESTS/mini_example2.4.blif
|
||||
|
||||
time
|
|
@ -0,0 +1,6 @@
|
|||
# The area/delay of k-variable LUTs:
|
||||
# k area delay
|
||||
1 1.00 1.00
|
||||
2 1.00 1.00
|
||||
3 1.00 1.00
|
||||
4 1.00 1.00
|
|
@ -0,0 +1,79 @@
|
|||
# Benchmark "test" written by ABC on Tue Aug 28 16:53:47 2007
|
||||
.model test
|
||||
.inputs a b c d e f g h i j k l m n o clk
|
||||
.outputs A0 B0 C0 D0 E0
|
||||
|
||||
.latch n53 D0 0
|
||||
.latch n57 E0 0
|
||||
|
||||
|
||||
.subckt mult_M1 a0=a a1=b a2=c a3=d b0=e b1=f b2=g b3=h c0=m0 c1=m1 c2=m2 c3=m3 c4=m4 c5=m5 c6=m6 c7=m7
|
||||
.subckt mult_M2 a0=a a1=b a2=c a3=d b0=i b1=j b2=k b3=l c0=m20 c1=m21 c2=m22 c3=m23 c4=m24 c5=m25 c6=m26 c7=m27
|
||||
|
||||
.names m0 m1 m20 m21 A0
|
||||
0011 1
|
||||
1111 1
|
||||
.names m24 m26 n58_1 B0
|
||||
000 1
|
||||
.names m22 n59 n57 n68 n58_1
|
||||
001- 0
|
||||
---1 0
|
||||
.names m23 m25 m27 n60 n59
|
||||
0111 0
|
||||
101- 0
|
||||
1100 0
|
||||
.names n61 n62 n63 n64 n60
|
||||
110- 0
|
||||
-0-1 0
|
||||
.names a b e f n61
|
||||
0110 1
|
||||
.names c d n62
|
||||
10 1
|
||||
.names g h n63
|
||||
01 1
|
||||
.names e f g n64
|
||||
011 1
|
||||
.names o n60 n66 n67 n57
|
||||
10-1 1
|
||||
111- 1
|
||||
.names a b m n66
|
||||
1-0 1
|
||||
-00 1
|
||||
.names a b m n n67
|
||||
0110 1
|
||||
1-11 1
|
||||
-011 1
|
||||
.names m25 m27 n60 n68
|
||||
110 1
|
||||
.names m3 n60 n71 n72 n70
|
||||
10-1 1
|
||||
-01- 1
|
||||
.names m6 m7 n71
|
||||
01 1
|
||||
.names m2 m4 n72
|
||||
00 1
|
||||
.names m3 m5 n71 n72 n73
|
||||
0111 1
|
||||
1011 1
|
||||
.names m4 m5 n60 n71 n74
|
||||
0101 1
|
||||
.names n57 n70 n73 n74 C0
|
||||
0--0 0
|
||||
-000 0
|
||||
.names m n53
|
||||
1 1
|
||||
.end
|
||||
|
||||
|
||||
.model mult_M1
|
||||
.inputs a0 a1 a2 a3 b0 b1 b2 b3
|
||||
.outputs c0 c1 c2 c3 c4 c5 c6 c7
|
||||
.blackbox
|
||||
.end
|
||||
|
||||
|
||||
.model mult_M2
|
||||
.inputs a0 a1 a2 a3 b0 b1 b2 b3
|
||||
.outputs c0 c1 c2 c3 c4 c5 c6 c7
|
||||
.blackbox
|
||||
.end
|
|
@ -0,0 +1,56 @@
|
|||
.model test
|
||||
.inputs a b c d e f g h i j k l m n o clk
|
||||
.outputs A0 B0 C0 D0 E0
|
||||
|
||||
.subckt mult_M1 a0=a a1=b a2=c a3=d b0=e b1=f b2=g b3=h c0=m0 c1=m1 c2=m2 c3=m3 c4=m4 c5=m5 c6=m6 c7=m7
|
||||
.subckt mult_M2 a0=a a1=b a2=c a3=d b0=i b1=j b2=k b3=l c0=m20 c1=m21 c2=m22 c3=m23 c4=m24 c5=m25 c6=m26 c7=m27
|
||||
|
||||
.latch m D0 re clk 0
|
||||
.latch o4 E0 re clk 0
|
||||
|
||||
.names a b o1
|
||||
01 1
|
||||
.names c d o2
|
||||
10 1
|
||||
.names e f g h o1 o2 o3
|
||||
100011 1
|
||||
101-11 1
|
||||
011--0 1
|
||||
.names o3 o1 m n o o4
|
||||
11101 1
|
||||
10111 1
|
||||
000-1 1
|
||||
.names m0 m1 m20 m21 A0
|
||||
1111 1
|
||||
0011 1
|
||||
.names o3 o4 m22 m23 m24 m25 m26 m27 B0
|
||||
11010101 1
|
||||
01010001 1
|
||||
11010001 1
|
||||
11010100 1
|
||||
11000101 1
|
||||
01000101 1
|
||||
1---0101 1
|
||||
.names o3 o4 m2 m3 m4 m5 m6 m7 C0
|
||||
1--10101 1
|
||||
01010001 1
|
||||
11----01 1
|
||||
11010--- 1
|
||||
01000101 1
|
||||
01000101 1
|
||||
1---0101 1
|
||||
|
||||
|
||||
.end
|
||||
|
||||
.model mult_M1
|
||||
.inputs a0 a1 a2 a3 b0 b1 b2 b3
|
||||
.outputs c0 c1 c2 c3 c4 c5 c6 c7
|
||||
.blackbox
|
||||
.end
|
||||
|
||||
.model mult_M2
|
||||
.inputs a0 a1 a2 a3 b0 b1 b2 b3
|
||||
.outputs c0 c1 c2 c3 c4 c5 c6 c7
|
||||
.blackbox
|
||||
.end
|
|
@ -0,0 +1,62 @@
|
|||
# Benchmark "test" written by ABC on Tue Aug 28 16:53:48 2007
|
||||
.model test
|
||||
.inputs a b c clk d e f g h i j k l m m0 m1 m2 m20 m21 m22 m23 m24 m25 m26 \
|
||||
m27 m3 m4 m5 m6 m7 n o
|
||||
.outputs A0 B0 C0 D0 E0
|
||||
|
||||
.latch n74 D0 0
|
||||
.latch n78 E0 0
|
||||
|
||||
.names m0 m1 m20 m21 A0
|
||||
0011 1
|
||||
1111 1
|
||||
.names m24 m26 n46 B0
|
||||
000 1
|
||||
.names m22 n47 n78 n56 n46
|
||||
001- 0
|
||||
---1 0
|
||||
.names m23 m25 m27 n48 n47
|
||||
0111 0
|
||||
101- 0
|
||||
1100 0
|
||||
.names n49 n50 n51 n52 n48
|
||||
110- 0
|
||||
-0-1 0
|
||||
.names a b e f n49
|
||||
0110 1
|
||||
.names c d n50
|
||||
10 1
|
||||
.names g h n51
|
||||
01 1
|
||||
.names e f g n52
|
||||
011 1
|
||||
.names o n48 n54 n55 n78
|
||||
10-1 1
|
||||
111- 1
|
||||
.names a b m n54
|
||||
1-0 1
|
||||
-00 1
|
||||
.names a b m n n55
|
||||
0110 1
|
||||
1-11 1
|
||||
-011 1
|
||||
.names m25 m27 n48 n56
|
||||
110 1
|
||||
.names m3 n48 n59 n60 n58
|
||||
10-1 1
|
||||
-01- 1
|
||||
.names m6 m7 n59
|
||||
01 1
|
||||
.names m2 m4 n60
|
||||
00 1
|
||||
.names m3 m5 n59 n60 n61
|
||||
0111 1
|
||||
1011 1
|
||||
.names m4 m5 n48 n59 n62
|
||||
0101 1
|
||||
.names n78 n58 n61 n62 C0
|
||||
0--0 0
|
||||
-000 0
|
||||
.names m n74
|
||||
1 1
|
||||
.end
|
|
@ -0,0 +1,40 @@
|
|||
.model test
|
||||
.inputs a b c d e f g h i j k l m n o clk m0 m1 m2 m3 m4 m5 m6 m7 m20 m21 m22 m23 m24 m25 m26 m27
|
||||
.outputs A0 B0 C0 D0 E0
|
||||
|
||||
.latch m D0 re clk 0
|
||||
.latch o4 E0 re clk 0
|
||||
|
||||
.names a b o1
|
||||
01 1
|
||||
.names c d o2
|
||||
10 1
|
||||
.names e f g h o1 o2 o3
|
||||
100011 1
|
||||
101-11 1
|
||||
011--0 1
|
||||
.names o3 o1 m n o o4
|
||||
11101 1
|
||||
10111 1
|
||||
000-1 1
|
||||
.names m0 m1 m20 m21 A0
|
||||
1111 1
|
||||
0011 1
|
||||
.names o3 o4 m22 m23 m24 m25 m26 m27 B0
|
||||
11010101 1
|
||||
01010001 1
|
||||
11010001 1
|
||||
11010100 1
|
||||
11000101 1
|
||||
01000101 1
|
||||
1---0101 1
|
||||
.names o3 o4 m2 m3 m4 m5 m6 m7 C0
|
||||
1--10101 1
|
||||
01010001 1
|
||||
11----01 1
|
||||
11010--- 1
|
||||
01000101 1
|
||||
01000101 1
|
||||
1---0101 1
|
||||
|
||||
.end
|
|
@ -0,0 +1,11 @@
|
|||
.model sample
|
||||
.inputs a00 a01 b00 b01
|
||||
.outputs y00 y01
|
||||
|
||||
.names a00 a01 y00
|
||||
11 1
|
||||
.names b00 b01 y01
|
||||
10 1
|
||||
|
||||
.end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.model Adder02
|
||||
.inputs a00 a01 b00 b01
|
||||
.outputs y00 y01 y02
|
||||
|
||||
.subckt FA a=a00 b=b00 cin=c s=y00 cout=00
|
||||
.subckt FA a=a01 b=b01 cin=00 s=y01 cout=y02
|
||||
.names c
|
||||
0
|
||||
.end
|
||||
|
||||
.model FA
|
||||
.inputs a b cin
|
||||
.outputs s cout
|
||||
.names a b k
|
||||
10 1
|
||||
01 1
|
||||
.names k cin s
|
||||
10 1
|
||||
01 1
|
||||
.names a b cin cout
|
||||
11- 1
|
||||
1-1 1
|
||||
-11 1
|
||||
.end
|
|
@ -0,0 +1,13 @@
|
|||
.model Adder02
|
||||
.inputs a00 a01
|
||||
.outputs y00
|
||||
|
||||
.subckt FA a=a00 b=a01 cout=y00
|
||||
.end
|
||||
|
||||
.model FA
|
||||
.inputs a b
|
||||
.outputs cout
|
||||
.names a b cout
|
||||
11 1
|
||||
.end
|
|
@ -0,0 +1,19 @@
|
|||
.model test
|
||||
.inputs A0 A1 B0 B1 start c
|
||||
.outputs C0 C1 C2
|
||||
|
||||
.subckt FA a=A0 b=A1 c=start carryout=CARRY1 sum=C0d
|
||||
.subckt FA a=A1 b=B1 c=CARRY1 carryout=C2d sum=C1d
|
||||
|
||||
.latch C0d C0 re c 0
|
||||
.latch C1d C1 re c 0
|
||||
.latch C2d C2 re c 0
|
||||
|
||||
.end
|
||||
|
||||
.model FA
|
||||
.inputs a b c
|
||||
.outputs carryout sum
|
||||
# test
|
||||
.blackbox extra words
|
||||
.end
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
CC := gcc-4.9
|
||||
CXX := g++-4.9
|
||||
LD := g++-4.9
|
||||
CP := cp
|
||||
|
||||
PROG := abc
|
||||
|
||||
MODULES := src/base/abc src/base/abci src/base/cmd \
|
||||
src/base/io src/base/main src/base/ver \
|
||||
src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco \
|
||||
src/aig/mem src/aig/dar src/aig/fra src/aig/cnf \
|
||||
src/aig/csw src/aig/ec src/aig/aig src/aig/kit \
|
||||
src/aig/bdc \
|
||||
src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \
|
||||
src/bdd/parse src/bdd/reo src/bdd/cas \
|
||||
src/map/fpga src/map/mapper src/map/mio \
|
||||
src/map/super src/map/if \
|
||||
src/misc/extra src/misc/mvc src/misc/st src/misc/util \
|
||||
src/misc/espresso src/misc/nm src/misc/vec \
|
||||
src/misc/hash \
|
||||
src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr \
|
||||
src/opt/sim src/opt/ret src/opt/res src/opt/lpk \
|
||||
src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \
|
||||
src/phys/place
|
||||
|
||||
default: $(PROG)
|
||||
|
||||
#OPTFLAGS := -DNDEBUG -O3
|
||||
OPTFLAGS := -g -O
|
||||
|
||||
CFLAGS += -w $(OPTFLAGS) $(patsubst %, -I%, $(MODULES))
|
||||
CFLAGS += -MD -MP
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
|
||||
#LIBS := -ldl -rdynamic -ltermcap
|
||||
LIBS := -ldl -rdynamic
|
||||
|
||||
SRC :=
|
||||
GARBAGE := core core.* *.stackdump ./tags $(PROG)
|
||||
|
||||
.PHONY: tags clean docs
|
||||
|
||||
include $(patsubst %, %/module.make, $(MODULES))
|
||||
|
||||
OBJ := \
|
||||
$(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \
|
||||
$(patsubst %.c, %.o, $(filter %.c, $(SRC))) \
|
||||
$(patsubst %.y, %.o, $(filter %.y, $(SRC)))
|
||||
|
||||
DEP := $(OBJ:.o=.d)
|
||||
|
||||
# implicit rules
|
||||
# Jason Luu Oct 26: Not necessary due to -MP -MD
|
||||
#%.d: %.c
|
||||
# ./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $@
|
||||
#
|
||||
#%.d: %.cc
|
||||
# ./depends.sh $(CXX) `dirname $*.cc` $(CXXFLAGS) $(CFLAGS) $*.cc > $@
|
||||
#
|
||||
#-include $(DEP)
|
||||
|
||||
# Actual targets
|
||||
|
||||
depend: $(DEP)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) $(OBJ) $(GARBAGE) $(OBJ:.o=.d)
|
||||
|
||||
tags:
|
||||
ctags -R .
|
||||
|
||||
$(PROG): $(OBJ) lib$(PROG).a
|
||||
$(LD) -o $@ $^ $(LIBS)
|
||||
|
||||
lib$(PROG).a: $(OBJ)
|
||||
ar rv $@ $?
|
||||
ranlib $@
|
||||
|
||||
docs:
|
||||
doxygen doxygen.conf
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "abc"=.\abc.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
Binary file not shown.
|
@ -0,0 +1,174 @@
|
|||
# global parameters
|
||||
set check # checks intermediate networks
|
||||
#set checkfio # prints warnings when fanins/fanouts are duplicated
|
||||
set checkread # checks new networks after reading from file
|
||||
set backup # saves backup networks retrived by "undo" and "recall"
|
||||
set savesteps 1 # sets the maximum number of backup networks to save
|
||||
set progressbar # display the progress bar
|
||||
|
||||
# program names for internal calls
|
||||
set dotwin dot.exe
|
||||
set dotunix dot
|
||||
set gsviewwin gsview32.exe
|
||||
set gsviewunix gv
|
||||
set siswin sis.exe
|
||||
set sisunix sis
|
||||
set mvsiswin mvsis.exe
|
||||
set mvsisunix mvsis
|
||||
set capowin MetaPl-Capo10.1-Win32.exe
|
||||
set capounix MetaPl-Capo10.1
|
||||
set gnuplotwin wgnuplot.exe
|
||||
set gnuplotunix gnuplot
|
||||
|
||||
# standard aliases
|
||||
alias b balance
|
||||
alias cl cleanup
|
||||
alias clp collapse
|
||||
alias esd ext_seq_dcs
|
||||
alias f fraig
|
||||
alias fs fraig_sweep
|
||||
alias fsto fraig_store
|
||||
alias fres fraig_restore
|
||||
alias ft fraig_trust
|
||||
alias lp lutpack
|
||||
alias pd print_dsd
|
||||
alias pex print_exdc -d
|
||||
alias pf print_factor
|
||||
alias pfan print_fanio
|
||||
alias pl print_level
|
||||
alias pio print_io
|
||||
alias pk print_kmap
|
||||
alias ps print_stats
|
||||
alias psu print_supp
|
||||
alias psy print_symm
|
||||
alias pun print_unate
|
||||
alias q quit
|
||||
alias r read
|
||||
alias r3 retime -M 3
|
||||
alias r3f retime -M 3 -f
|
||||
alias r3b retime -M 3 -b
|
||||
alias ren renode
|
||||
alias rh read_hie
|
||||
alias rl read_blif
|
||||
alias rb read_bench
|
||||
alias ret retime
|
||||
alias rp read_pla
|
||||
alias rt read_truth
|
||||
alias rv read_verilog
|
||||
alias rvl read_verlib
|
||||
alias rsup read_super mcnc5_old.super
|
||||
alias rlib read_library
|
||||
alias rlibc read_library cadence.genlib
|
||||
alias rw rewrite
|
||||
alias rwz rewrite -z
|
||||
alias rf refactor
|
||||
alias rfz refactor -z
|
||||
alias re restructure
|
||||
alias rez restructure -z
|
||||
alias rs resub
|
||||
alias rsz resub -z
|
||||
alias sa set autoexec ps
|
||||
alias scl scleanup
|
||||
alias sif if -s
|
||||
alias so source -x
|
||||
alias st strash
|
||||
alias sw sweep
|
||||
alias ssw ssweep
|
||||
alias tr0 trace_start
|
||||
alias tr1 trace_check
|
||||
alias trt "r c.blif; st; tr0; b; tr1"
|
||||
alias u undo
|
||||
alias w write
|
||||
alias wa write_aiger
|
||||
alias wb write_bench
|
||||
alias wc write_cnf
|
||||
alias wh write_hie
|
||||
alias wl write_blif
|
||||
alias wp write_pla
|
||||
alias wv write_verilog
|
||||
|
||||
# standard scripts
|
||||
alias share "b; ren -s; fx; b"
|
||||
alias sharedsd "b; ren -b; dsd -g; sw; fx; b"
|
||||
alias resyn "b; rw; rwz; b; rwz; b"
|
||||
alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
|
||||
alias resyn2a "b; rw; b; rw; rwz; b; rwz; b"
|
||||
alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b"
|
||||
alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
|
||||
alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
|
||||
alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
|
||||
alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore"
|
||||
alias rwsat "st; rw -l; b -l; rw -l; rf -l"
|
||||
alias rwsat2 "st; rw -l; b -l; rw -l; rf -l; fraig; rw -l; b -l; rw -l; rf -l"
|
||||
alias shake "st; ps; sat -C 5000; rw -l; ps; sat -C 5000; b -l; rf -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000; rwz -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000"
|
||||
|
||||
# resubstitution scripts for the IWLS paper
|
||||
alias src_rw "st; rw -l; rwz -l; rwz -l"
|
||||
alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l"
|
||||
alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l"
|
||||
alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b"
|
||||
alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
|
||||
|
||||
# experimental implementation of don't-cares
|
||||
alias resyn2rsdc "b; rs -K 6 -F 2; rw; rs -K 6 -N 2 -F 2; rf; rs -K 8 -F 2; b; rs -K 8 -N 2 -F 2; rw; rs -K 10 -F 2; rwz; rs -K 10 -N 2 -F 2; b; rs -K 12 -F 2; rfz; rs -K 12 -N 2 -F 2; rwz; b"
|
||||
alias compress2rsdc "b -l; rs -K 6 -F 2 -l; rw -l; rs -K 6 -N 2 -F 2 -l; rf -l; rs -K 8 -F 2 -l; b -l; rs -K 8 -N 2 -F 2 -l; rw -l; rs -K 10 -F 2 -l; rwz -l; rs -K 10 -N 2 -F 2 -l; b -l; rs -K 12 -F 2 -l; rfz -l; rs -K 12 -N 2 -F 2 -l; rwz -l; b -l"
|
||||
|
||||
# minimizing for FF literals
|
||||
alias fflitmin "compress2rs; ren; sop; ps -f"
|
||||
|
||||
# temporaries
|
||||
#alias t "rvl th/lib.v; rvv th/t2.v"
|
||||
#alias t "so c/pure_sat/test.c"
|
||||
#alias t "r c/14/csat_998.bench; st; ps"
|
||||
#alias t0 "r res.blif; aig; mfs"
|
||||
#alias t "r res2.blif; aig; mfs"
|
||||
|
||||
#alias tt "r a/quip_opt/nut_001_opt.blif"
|
||||
#alias ttb "wh a/quip_opt/nut_001_opt.blif 1.blif"
|
||||
#alias ttv "wh a/quip_opt/nut_001_opt.blif 1.v"
|
||||
|
||||
alias reach "st; ps; compress2; ps; qrel; ps; compress2; ps; qreach -v; ps"
|
||||
|
||||
alias qs1 "qvar -I 96 -u; ps; qbf -P 96"
|
||||
alias qs2 "qvar -I 96 -u; qvar -I 97 -u; ps; qbf -P 96"
|
||||
alias qs3 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; ps; qbf -P 96"
|
||||
alias qs4 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; ps; qbf -P 96"
|
||||
alias qs5 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; ps; qbf -P 96"
|
||||
alias qs6 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; ps; qbf -P 96"
|
||||
alias qs7 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; ps; qbf -P 96"
|
||||
alias qs8 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; ps; qbf -P 96"
|
||||
alias qs9 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; ps; qbf -P 96"
|
||||
alias qsA "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; qvar -I 105 -u; ps; qbf -P 96"
|
||||
|
||||
alias chnew "st; haig_start; resyn2; haig_use"
|
||||
alias chnewrs "st; haig_start; resyn2rs; haig_use"
|
||||
|
||||
alias stdsd "r test/6in.blif; st; ps; u; bdd; dsd -g; st; ps"
|
||||
alias trec "rec_start; r c.blif; st; rec_add; rec_use"
|
||||
alias trec4 "rec_start -K 4; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec5 "rec_start -K 5; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec6 "rec_start -K 6; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec7 "rec_start -K 7; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec8 "rec_start -K 8; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec10 "rec_start -K 10; r i10.blif; st; rec_add; rec_use"
|
||||
alias trec12 "rec_start -K 12; r i10.blif; st; rec_add; rec_use"
|
||||
|
||||
#alias tsh "r i10_if.blif; st; ps; u; sw; st; ps; cec"
|
||||
alias tst4 "r i10_if4.blif; st; ps; r x/rec4_.blif; st; rec_start; r i10_if4.blif; st -r; ps; cec"
|
||||
alias tst4n "r i10_if4.blif; st; ps; r 5npn/all_functions.aig; st; rec_start; r i10_if4.blif; st -r; ps; cec"
|
||||
alias tst6 "r i10_if6.blif; st; ps; r x/rec6_16_.blif; st; rec_start; r i10_if6.blif; st -r; ps; cec"
|
||||
|
||||
#alias t "r c.blif; st; wc c.cnf"
|
||||
#alias t "r test/dsdmap6.blif; lutpack -vw; cec"
|
||||
#alias t "r i10_if4.blif; lp"
|
||||
#alias t1 "r pj1_if4.blif; lp"
|
||||
#alias t2 "r pj1_if6.blif; lp"
|
||||
#alias t "r pj/pj1.blif; st; dfraig -v"
|
||||
#alias t "r c/16/csat_2.bench; st; dfraig -C 100 -v -r"
|
||||
#alias t "r c/16/csat_147.bench; st; dfraig -C 10 -v -r"
|
||||
#alias t "r i10.blif; st; ps; csweep; ps; cec"
|
||||
#alias t "r c/5/csat_777.bench; st; csweep -v"
|
||||
#alias t "r i10.blif; st; drw -v"
|
||||
alias t "r c.blif; st; drf"
|
||||
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "abclib"=.\abclib.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
# Microsoft Developer Studio Project File - Name="abctestlib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=abctestlib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "abctestlib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "abctestlib.mak" CFG="abctestlib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "abctestlib - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "abctestlib - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "abctestlib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_release.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abctestlib.exe"
|
||||
|
||||
!ELSEIF "$(CFG)" == "abctestlib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_debug.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abctestlib.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "abctestlib - Win32 Release"
|
||||
# Name "abctestlib - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\demo.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "abctestlib"=.\abctestlib.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
.model accum
|
||||
.inputs top^clock top^reset_n top^D~0 top^D~1 top^D~2 top^D~3
|
||||
.outputs top^Q~0 top^Q~1 top^Q~2 top^Q~3
|
||||
|
||||
.names gnd
|
||||
.names hbpad
|
||||
.names vcc
|
||||
1
|
||||
|
||||
.names top^reset_n top^MULTI_PORT_MUX~0^LOGICAL_NOT~1 gnd top^ADD~2^ADDER_FUNC~15 top^MULTI_PORT_MUX~0^MUX_2~11
|
||||
1-1- 1
|
||||
-1-1 1
|
||||
|
||||
.latch top^MULTI_PORT_MUX~0^MUX_2~11 top^FF_NODE~3 re top^clock 0
|
||||
|
||||
.names gnd top^FF_NODE~3 top^D~0 top^ADD~2^ADDER_FUNC~15
|
||||
001 1
|
||||
010 1
|
||||
100 1
|
||||
111 1
|
||||
|
||||
.names gnd top^FF_NODE~3 top^D~0 top^ADD~2^CARRY_FUNC~16
|
||||
011 1
|
||||
100 1
|
||||
110 1
|
||||
111 1
|
||||
|
||||
.names top^ADD~2^CARRY_FUNC~16 top^FF_NODE~4 top^D~1 top^ADD~2^ADDER_FUNC~17
|
||||
001 1
|
||||
010 1
|
||||
100 1
|
||||
111 1
|
||||
|
||||
.names top^reset_n top^MULTI_PORT_MUX~0^LOGICAL_NOT~1 gnd top^ADD~2^ADDER_FUNC~17 top^MULTI_PORT_MUX~0^MUX_2~12
|
||||
1-1- 1
|
||||
-1-1 1
|
||||
|
||||
.latch top^MULTI_PORT_MUX~0^MUX_2~12 top^FF_NODE~4 re top^clock 0
|
||||
|
||||
.names top^ADD~2^CARRY_FUNC~16 top^FF_NODE~4 top^D~1 top^ADD~2^CARRY_FUNC~18
|
||||
011 1
|
||||
100 1
|
||||
110 1
|
||||
111 1
|
||||
|
||||
.names top^ADD~2^CARRY_FUNC~18 top^FF_NODE~5 top^D~2 top^ADD~2^ADDER_FUNC~19
|
||||
001 1
|
||||
010 1
|
||||
100 1
|
||||
111 1
|
||||
|
||||
.names top^reset_n top^MULTI_PORT_MUX~0^LOGICAL_NOT~1 gnd top^ADD~2^ADDER_FUNC~19 top^MULTI_PORT_MUX~0^MUX_2~13
|
||||
1-1- 1
|
||||
-1-1 1
|
||||
|
||||
.latch top^MULTI_PORT_MUX~0^MUX_2~13 top^FF_NODE~5 re top^clock 0
|
||||
|
||||
.names top^ADD~2^CARRY_FUNC~18 top^FF_NODE~5 top^D~2 top^ADD~2^CARRY_FUNC~20
|
||||
011 1
|
||||
100 1
|
||||
110 1
|
||||
111 1
|
||||
|
||||
.names top^ADD~2^CARRY_FUNC~20 top^FF_NODE~6 top^D~3 top^ADD~2^ADDER_FUNC~21
|
||||
001 1
|
||||
010 1
|
||||
100 1
|
||||
111 1
|
||||
|
||||
.names top^reset_n top^MULTI_PORT_MUX~0^LOGICAL_NOT~1 gnd top^ADD~2^ADDER_FUNC~21 top^MULTI_PORT_MUX~0^MUX_2~14
|
||||
1-1- 1
|
||||
-1-1 1
|
||||
|
||||
.latch top^MULTI_PORT_MUX~0^MUX_2~14 top^FF_NODE~6 re top^clock 0
|
||||
|
||||
.names top^reset_n top^MULTI_PORT_MUX~0^LOGICAL_NOT~1
|
||||
0 1
|
||||
|
||||
.names top^FF_NODE~3 top^Q~0
|
||||
1 1
|
||||
.names top^FF_NODE~4 top^Q~1
|
||||
1 1
|
||||
.names top^FF_NODE~5 top^Q~2
|
||||
1 1
|
||||
.names top^FF_NODE~6 top^Q~3
|
||||
1 1
|
||||
.end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
module accum (clock, reset_n, D, Q);
|
||||
input clock, reset_n;
|
||||
input [3:0] D;
|
||||
output [3:0] Q;
|
||||
reg [3:0] tmp;
|
||||
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset_n)
|
||||
tmp <= 4'b0000;
|
||||
else
|
||||
tmp <= tmp + D;
|
||||
end
|
||||
assign Q = tmp;
|
||||
endmodule
|
|
@ -0,0 +1,18 @@
|
|||
Copyright (c) The Regents of the University of California. All rights reserved.
|
||||
|
||||
Permission is hereby granted, without written agreement and without license or
|
||||
royalty fees, to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, provided that the above copyright notice and
|
||||
the following two paragraphs appear in all copies of this software.
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
|
||||
THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
|
||||
CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
||||
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
|
||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [demo.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [ABC as a static library.]
|
||||
|
||||
Synopsis [A demo program illustrating the use of ABC as a static library.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// procedures to start and stop the ABC framework
|
||||
// (should be called before and after the ABC procedures are called)
|
||||
extern void Abc_Start();
|
||||
extern void Abc_Stop();
|
||||
|
||||
// procedures to get the ABC framework and execute commands in it
|
||||
extern void * Abc_FrameGetGlobalFrame();
|
||||
extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [The main() procedure.]
|
||||
|
||||
Description [This procedure compiles into a stand-alone program for
|
||||
DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered
|
||||
for rewriting should be given as a command-line argument. Implementation
|
||||
of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv,
|
||||
"DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
// parameters
|
||||
int fUseResyn2 = 0;
|
||||
int fPrintStats = 1;
|
||||
int fVerify = 1;
|
||||
// variables
|
||||
void * pAbc;
|
||||
char * pFileName;
|
||||
char Command[1000];
|
||||
int clkRead, clkResyn, clkVer, clk;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// get the input file name
|
||||
if ( argc != 2 )
|
||||
{
|
||||
printf( "Wrong number of command-line arguments.\n" );
|
||||
return 1;
|
||||
}
|
||||
pFileName = argv[1];
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// start the ABC framework
|
||||
Abc_Start();
|
||||
pAbc = Abc_FrameGetGlobalFrame();
|
||||
|
||||
clk = clock();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// read the file
|
||||
sprintf( Command, "read %s", pFileName );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// balance
|
||||
sprintf( Command, "balance" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
clkRead = clock() - clk;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// print stats
|
||||
if ( fPrintStats )
|
||||
{
|
||||
sprintf( Command, "print_stats" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
clk = clock();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// synthesize
|
||||
if ( fUseResyn2 )
|
||||
{
|
||||
sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
clkResyn = clock() - clk;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// print stats
|
||||
if ( fPrintStats )
|
||||
{
|
||||
sprintf( Command, "print_stats" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// write the result in blif
|
||||
sprintf( Command, "write_blif result.blif" );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// perform verification
|
||||
clk = clock();
|
||||
if ( fVerify )
|
||||
{
|
||||
sprintf( Command, "cec %s result.blif", pFileName );
|
||||
if ( Cmd_CommandExecute( pAbc, Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
clkVer = clock() - clk;
|
||||
|
||||
printf( "Reading = %6.2f sec ", (float)(clkRead)/(float)(CLOCKS_PER_SEC) );
|
||||
printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) );
|
||||
printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// stop the ABC framework
|
||||
Abc_Stop();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/sh
|
||||
#echo "## Got: $*"
|
||||
CC="$1"
|
||||
DIR="$2"
|
||||
shift 2
|
||||
case "$DIR" in
|
||||
"" | ".")
|
||||
$CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@'
|
||||
;;
|
||||
*)
|
||||
$CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@"
|
||||
;;
|
||||
esac
|
Binary file not shown.
|
@ -0,0 +1,26 @@
|
|||
Often the code comes directly from a Windows computer.
|
||||
The following steps may be needed to compile it on UNIX:
|
||||
|
||||
>> dos2unix Makefile Makefile
|
||||
>> dos2unix depends.sh depends.sh
|
||||
>> chmod 755 depends.sh
|
||||
>> make // on Solaris, try "gmake"
|
||||
|
||||
If compiling as a static library, it is necessary to uncomment
|
||||
#define _LIB in "src/abc/main/main.c"
|
||||
|
||||
Several things to try if it does not compile on your platform:
|
||||
- Try running all code (not only Makefile and depends.sh) through dos2unix
|
||||
- Try the following actions:
|
||||
(a) Remove flags from the libs line (LIBS :=) in Makefile
|
||||
(b) Remove "src\base\main\libSupport.c" from "src\base\main\module.make"
|
||||
(c) Comment calls to Libs_Init() and Libs_End() in "src\base\main\mainInit.c"
|
||||
- Try linking with gcc (rather than g++)
|
||||
For this replace "LD := g++" with "LD := gcc -lm" in Makefile
|
||||
- If your Linux distributin does not have "readline", you may have problems
|
||||
compiling ABC with gcc. Please try installing this library from
|
||||
http://tiswww.case.edu/php/chet/readline/rltop.html
|
||||
|
||||
|
||||
Finally, run regression test:
|
||||
abc>>> so regtest.script
|
|
@ -0,0 +1,18 @@
|
|||
r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps
|
||||
r examples/C2670.blif; st; w 1.aig; cec 1.aig
|
||||
r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench
|
||||
r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn
|
||||
r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps
|
||||
r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps
|
||||
r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps
|
||||
r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps
|
||||
r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps
|
||||
r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps
|
||||
r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps
|
||||
r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps
|
||||
r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps
|
||||
r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps
|
||||
r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif
|
||||
r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif
|
||||
r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif
|
||||
time
|
|
@ -0,0 +1,96 @@
|
|||
UC Berkeley, ABC 1.01 (compiled Dec 25 2006 17:15:00)
|
||||
abc 01> so regtest.script
|
||||
abc - > r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps
|
||||
Networks are equivalent.
|
||||
examples/apex4: i/o = 9/ 19 lat = 0 nd = 1172 aig = 4365 lev = 7
|
||||
The shared BDD size is 917 nodes. BDD construction time = 0.04 sec
|
||||
A simple supergate library is derived from gate library "mcnc_temp.genlib".
|
||||
Loaded 20 unique 5-input supergates from "mcnc_temp.super". Time = 0.02 sec
|
||||
Networks are equivalent.
|
||||
examples/apex4: i/o = 9/ 19 lat = 0 nd = 1734 aig = 2576 lev = 12
|
||||
abc - > r examples/C2670.blif; st; w 1.aig; cec 1.aig
|
||||
Networks are equivalent after structural hashing.
|
||||
abc - > r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench
|
||||
Networks are equivalent after structural hashing.
|
||||
abc - > r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn
|
||||
Networks are equivalent.
|
||||
abc - > r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps
|
||||
Networks are equivalent.
|
||||
C2670.iscas : i/o = 233/ 140 lat = 0 nd = 120 aig = 1056 lev = 4
|
||||
Networks are equivalent.
|
||||
C2670.iscas : i/o = 233/ 140 lat = 0 nd = 467 aig = 651 lev = 14
|
||||
abc - > r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps
|
||||
Networks are equivalent.
|
||||
frg2 : i/o = 143/ 139 lat = 0 nd = 1648 aig = 2268 lev = 18
|
||||
The shared BDD size is 1672 nodes. BDD construction time = 0.14 sec
|
||||
Networks are equivalent.
|
||||
frg2 : i/o = 143/ 139 lat = 0 nd = 533 aig = 778 lev = 8
|
||||
abc - > r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps
|
||||
Networks are equivalent.
|
||||
frg2 : i/o = 143/ 139 lat = 0 nd = 2868 aig = 4221 lev = 38
|
||||
The shared BDD size is 1684 nodes. BDD construction time = 0.14 sec
|
||||
Networks are equivalent.
|
||||
frg2 : i/o = 143/ 139 lat = 0 nd = 2331 aig = 3180 lev = 20
|
||||
abc - > r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps
|
||||
Networks are equivalent.
|
||||
i10 : i/o = 257/ 224 lat = 0 nd = 808 aig = 2630 lev = 12
|
||||
Networks are equivalent.
|
||||
i10 : i/o = 257/ 224 lat = 0 nd = 1555 aig = 1980 lev = 24
|
||||
abc - > r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps
|
||||
Currently stored 3 networks with 5801 nodes will be fraiged.
|
||||
Total fraiging time = 0.39 sec
|
||||
Performing FPGA mapping with choices.
|
||||
Networks are equivalent.
|
||||
i10 : i/o = 257/ 224 lat = 0 nd = 798 aig = 2543 lev = 12
|
||||
Performing mapping with choices.
|
||||
Networks are equivalent.
|
||||
i10 : i/o = 257/ 224 lat = 0 nd = 1463 aig = 1993 lev = 23
|
||||
abc - > r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps
|
||||
Networks are equivalent after structural hashing.
|
||||
exCombCkt : i/o = 1769/1063 lat = 0 nd = 5984 aig = 23156 lev = 52
|
||||
Networks are equivalent.
|
||||
exCombCkt : i/o = 1769/1063 lat = 0 nd = 11474 aig = 16032 lev = 80
|
||||
abc - > r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps
|
||||
examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
|
||||
Networks are equivalent.
|
||||
s38417 : i/o = 1664/1742 lat = 0 nd = 3479 aig = 10120 lev = 9
|
||||
abc - > r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps
|
||||
examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
|
||||
examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
|
||||
Networks are equivalent.
|
||||
s38417 : i/o = 28/ 106 lat = 1636 nd = 3479 aig = 10120 lev = 9
|
||||
examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
|
||||
Networks are equivalent.
|
||||
s38417 : i/o = 28/ 106 lat = 1636 nd = 7189 aig = 8689 lev = 17
|
||||
abc - > r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps
|
||||
The network was strashed and balanced before FPGA mapping.
|
||||
Networks are equivalent.
|
||||
examples/s38584: i/o = 12/ 278 lat = 1452 nd = 4266 aig = 12569 lev = 10
|
||||
The network was strashed and balanced before mapping.
|
||||
Networks are equivalent.
|
||||
examples/s38584: i/o = 12/ 278 lat = 1452 nd = 8135 aig = 10674 lev = 18
|
||||
abc - > r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps
|
||||
The shared BDD size is 181 nodes.
|
||||
BDD nodes in the transition relation before reordering 557.
|
||||
BDD nodes in the transition relation after reordering 456.
|
||||
Reachability analysis completed in 151 iterations.
|
||||
The number of minterms in the reachable state set = 8865.
|
||||
BDD nodes in the unreachable states before reordering 124.
|
||||
BDD nodes in the unreachable states after reordering 113.
|
||||
EXDC network statistics:
|
||||
exdc : i/o = 21/ 21 lat = 0 nd = 21 cube = 86 lev = 2
|
||||
Networks are equivalent.
|
||||
s444 : i/o = 3/ 6 lat = 21 nd = 82 aig = 176 lev = 7
|
||||
abc - > r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif
|
||||
Networks are equivalent after structural hashing.
|
||||
abc - > r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif
|
||||
s5378_5_frames: i/o = 175/ 245 lat = 164 and = 6629 (exor = 115) lev = 59
|
||||
s5378_5_frames: i/o = 175/ 245 lat = 182 nd = 6957 cube = 6956 lev = 50
|
||||
Networks are equivalent after framing.
|
||||
abc - > r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif
|
||||
s6669 : i/o = 83/ 55 lat = 239 nd = 3080 cube = 3080 lev = 93
|
||||
s6669 : i/o = 83/ 55 lat = 183 and = 1915 (exor = 371) lev = 97
|
||||
Networks are equivalent after fraiging.
|
||||
abc - > time
|
||||
elapse: 44.07 seconds, total: 44.07 seconds
|
||||
abc 150>
|
|
@ -0,0 +1,29 @@
|
|||
.model simple
|
||||
.inputs top^clock top^enable
|
||||
.outputs top^value_out
|
||||
|
||||
.names gnd
|
||||
.names hbpad
|
||||
.names vcc
|
||||
1
|
||||
|
||||
.names top^LOGICAL_EQUAL~1^LOGICAL_AND~7 top^MULTI_PORT_MUX~0^LOGICAL_NOT~2 gnd top^FF_NODE~3 top^MULTI_PORT_MUX~0^MUX_2~5
|
||||
1-1- 1
|
||||
-1-1 1
|
||||
|
||||
.latch top^MULTI_PORT_MUX~0^MUX_2~5 top^FF_NODE~3 re top^clock 0
|
||||
|
||||
.names top^enable vcc top^LOGICAL_EQUAL~1^LOGICAL_XNOR~6^LOGICAL_XNOR~8
|
||||
00 1
|
||||
11 1
|
||||
|
||||
.names top^LOGICAL_EQUAL~1^LOGICAL_XNOR~6^LOGICAL_XNOR~8 top^LOGICAL_EQUAL~1^LOGICAL_AND~7
|
||||
1 1
|
||||
|
||||
.names top^LOGICAL_EQUAL~1^LOGICAL_AND~7 top^MULTI_PORT_MUX~0^LOGICAL_NOT~2
|
||||
0 1
|
||||
|
||||
.names top^FF_NODE~3 top^value_out
|
||||
1 1
|
||||
.end
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Test enable circuitry
|
||||
|
||||
module simple(clock,
|
||||
enable,
|
||||
value_out
|
||||
);
|
||||
|
||||
input clock;
|
||||
input enable;
|
||||
reg temp;
|
||||
output value_out;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (enable == 1'b1) begin
|
||||
temp <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
assign value_out = temp;
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,498 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aig.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __AIG_H__
|
||||
#define __AIG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Aig_Man_t_ Aig_Man_t;
|
||||
typedef struct Aig_Obj_t_ Aig_Obj_t;
|
||||
typedef struct Aig_MmFixed_t_ Aig_MmFixed_t;
|
||||
typedef struct Aig_MmFlex_t_ Aig_MmFlex_t;
|
||||
typedef struct Aig_MmStep_t_ Aig_MmStep_t;
|
||||
|
||||
// object types
|
||||
typedef enum {
|
||||
AIG_OBJ_NONE, // 0: non-existent object
|
||||
AIG_OBJ_CONST1, // 1: constant 1
|
||||
AIG_OBJ_PI, // 2: primary input
|
||||
AIG_OBJ_PO, // 3: primary output
|
||||
AIG_OBJ_BUF, // 4: buffer node
|
||||
AIG_OBJ_AND, // 5: AND node
|
||||
AIG_OBJ_EXOR, // 6: EXOR node
|
||||
AIG_OBJ_LATCH, // 7: latch
|
||||
AIG_OBJ_VOID // 8: unused object
|
||||
} Aig_Type_t;
|
||||
|
||||
// the AIG node
|
||||
struct Aig_Obj_t_ // 8 words
|
||||
{
|
||||
void * pData; // misc (cuts, copy, etc)
|
||||
Aig_Obj_t * pNext; // strashing table
|
||||
Aig_Obj_t * pFanin0; // fanin
|
||||
Aig_Obj_t * pFanin1; // fanin
|
||||
unsigned long Type : 3; // object type
|
||||
unsigned long fPhase : 1; // value under 000...0 pattern
|
||||
unsigned long fMarkA : 1; // multipurpose mask
|
||||
unsigned long fMarkB : 1; // multipurpose mask
|
||||
unsigned long nRefs : 26; // reference count
|
||||
unsigned Level : 24; // the level of this node
|
||||
unsigned nCuts : 8; // the number of cuts
|
||||
int TravId; // unique ID of last traversal involving the node
|
||||
int Id; // unique ID of the node
|
||||
};
|
||||
|
||||
// the AIG manager
|
||||
struct Aig_Man_t_
|
||||
{
|
||||
// AIG nodes
|
||||
Vec_Ptr_t * vPis; // the array of PIs
|
||||
Vec_Ptr_t * vPos; // the array of POs
|
||||
Vec_Ptr_t * vObjs; // the array of all nodes (optional)
|
||||
Vec_Ptr_t * vBufs; // the array of buffers
|
||||
Aig_Obj_t * pConst1; // the constant 1 node
|
||||
Aig_Obj_t Ghost; // the ghost node
|
||||
int nRegs; // the number of registers (registers are last POs)
|
||||
int nAsserts; // the number of asserts among POs (asserts are first POs)
|
||||
// AIG node counters
|
||||
int nObjs[AIG_OBJ_VOID];// the number of objects by type
|
||||
int nCreated; // the number of created objects
|
||||
int nDeleted; // the number of deleted objects
|
||||
// structural hash table
|
||||
Aig_Obj_t ** pTable; // structural hash table
|
||||
int nTableSize; // structural hash table size
|
||||
// representation of fanouts
|
||||
int * pFanData; // the database to store fanout information
|
||||
int nFansAlloc; // the size of fanout representation
|
||||
Vec_Vec_t * vLevels; // used to update timing information
|
||||
int nBufReplaces; // the number of times replacement led to a buffer
|
||||
int nBufFixes; // the number of times buffers were propagated
|
||||
int nBufMax; // the maximum number of buffers during computation
|
||||
// topological order
|
||||
unsigned * pOrderData;
|
||||
int nOrderAlloc;
|
||||
int iPrev;
|
||||
int iNext;
|
||||
int nAndTotal;
|
||||
int nAndPrev;
|
||||
// representatives
|
||||
Aig_Obj_t ** pEquivs; // linked list of equivalent nodes (when choices are used)
|
||||
Aig_Obj_t ** pReprs; // representatives of each node
|
||||
int nReprsAlloc; // the number of allocated representatives
|
||||
// various data members
|
||||
Aig_MmFixed_t * pMemObjs; // memory manager for objects
|
||||
Vec_Int_t * vLevelR; // the reverse level of the nodes
|
||||
int nLevelMax; // maximum number of levels
|
||||
void * pData; // the temporary data
|
||||
int nTravIds; // the current traversal ID
|
||||
int fCatchExor; // enables EXOR nodes
|
||||
// timing statistics
|
||||
int time1;
|
||||
int time2;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define AIG_MIN(a,b) (((a) < (b))? (a) : (b))
|
||||
#define AIG_MAX(a,b) (((a) > (b))? (a) : (b))
|
||||
#define AIG_ABS(a) (((a) >= 0)? (a) :-(a))
|
||||
#define AIG_INFINITY (100000000)
|
||||
|
||||
#ifndef PRT
|
||||
#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
|
||||
#endif
|
||||
|
||||
static inline int Aig_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); }
|
||||
static inline int Aig_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
|
||||
static inline int Aig_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; }
|
||||
static inline void Aig_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); }
|
||||
static inline void Aig_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); }
|
||||
static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); }
|
||||
|
||||
static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) & ~01); }
|
||||
static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) ^ 01); }
|
||||
static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((unsigned long)(p) ^ (c)); }
|
||||
static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int )(((unsigned long)p) & 01); }
|
||||
|
||||
static inline int Aig_ManPiNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PI]; }
|
||||
static inline int Aig_ManPoNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PO]; }
|
||||
static inline int Aig_ManBufNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_BUF]; }
|
||||
static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]; }
|
||||
static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_EXOR]; }
|
||||
static inline int Aig_ManLatchNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_LATCH]; }
|
||||
static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR]; }
|
||||
static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; }
|
||||
static inline int Aig_ManObjNum( Aig_Man_t * p ) { return p->nCreated - p->nDeleted; }
|
||||
static inline int Aig_ManObjIdMax( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs); }
|
||||
static inline int Aig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; }
|
||||
|
||||
static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); }
|
||||
static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; }
|
||||
static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; }
|
||||
static inline Aig_Obj_t * Aig_ManPi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, i); }
|
||||
static inline Aig_Obj_t * Aig_ManPo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, i); }
|
||||
static inline Aig_Obj_t * Aig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, Aig_ManPiNum(p)-Aig_ManRegNum(p)+i); }
|
||||
static inline Aig_Obj_t * Aig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, Aig_ManPoNum(p)-Aig_ManRegNum(p)+i); }
|
||||
static inline Aig_Obj_t * Aig_ManObj( Aig_Man_t * p, int i ) { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; }
|
||||
|
||||
static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return (Aig_Type_t)pObj->Type; }
|
||||
static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_NONE; }
|
||||
static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; }
|
||||
static inline int Aig_ObjIsPi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI; }
|
||||
static inline int Aig_ObjIsPo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PO; }
|
||||
static inline int Aig_ObjIsBuf( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_BUF; }
|
||||
static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND; }
|
||||
static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_EXOR; }
|
||||
static inline int Aig_ObjIsLatch( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_LATCH; }
|
||||
static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; }
|
||||
static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI || pObj->Type == AIG_OBJ_PO || pObj->Type == AIG_OBJ_CONST1; }
|
||||
static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR || pObj->Type == AIG_OBJ_LATCH; }
|
||||
|
||||
static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; }
|
||||
static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; }
|
||||
static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; }
|
||||
|
||||
static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; }
|
||||
static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds; }
|
||||
static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; }
|
||||
static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds); }
|
||||
static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds - 1); }
|
||||
|
||||
static inline int Aig_ObjTravId( Aig_Obj_t * pObj ) { return (int)pObj->pData; }
|
||||
static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; }
|
||||
static inline int Aig_ObjPhaseReal( Aig_Obj_t * pObj ) { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1; }
|
||||
static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; }
|
||||
static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; }
|
||||
static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; }
|
||||
static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; }
|
||||
static inline int Aig_ObjFaninId0( Aig_Obj_t * pObj ) { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; }
|
||||
static inline int Aig_ObjFaninId1( Aig_Obj_t * pObj ) { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; }
|
||||
static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); }
|
||||
static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); }
|
||||
static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); }
|
||||
static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); }
|
||||
static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; }
|
||||
static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; }
|
||||
static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; }
|
||||
static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; }
|
||||
static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { return pObj->Level; }
|
||||
static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; }
|
||||
static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); }
|
||||
static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); }
|
||||
static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin )
|
||||
{
|
||||
if ( Aig_ObjFanin0(pObj) == pFanin ) return 0;
|
||||
if ( Aig_ObjFanin1(pObj) == pFanin ) return 1;
|
||||
assert(0); return -1;
|
||||
}
|
||||
static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout )
|
||||
{
|
||||
if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj);
|
||||
if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj);
|
||||
assert(0); return -1;
|
||||
}
|
||||
|
||||
// create the ghost of the new node
|
||||
static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type )
|
||||
{
|
||||
Aig_Obj_t * pGhost;
|
||||
assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) );
|
||||
assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) );
|
||||
assert( Type == AIG_OBJ_PI || Aig_Regular(p0) != Aig_Regular(p1) );
|
||||
pGhost = Aig_ManGhost(p);
|
||||
pGhost->Type = Type;
|
||||
if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id )
|
||||
{
|
||||
pGhost->pFanin0 = p0;
|
||||
pGhost->pFanin1 = p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pGhost->pFanin0 = p1;
|
||||
pGhost->pFanin1 = p0;
|
||||
}
|
||||
return pGhost;
|
||||
}
|
||||
|
||||
// internal memory manager
|
||||
static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p )
|
||||
{
|
||||
extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p );
|
||||
Aig_Obj_t * pTemp;
|
||||
pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs );
|
||||
memset( pTemp, 0, sizeof(Aig_Obj_t) );
|
||||
Vec_PtrPush( p->vObjs, pTemp );
|
||||
pTemp->Id = p->nCreated++;
|
||||
return pTemp;
|
||||
}
|
||||
static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry )
|
||||
{
|
||||
extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry );
|
||||
assert( pEntry->nRefs == 0 );
|
||||
pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node
|
||||
Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry );
|
||||
p->nDeleted++;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// iterator over the primary inputs
|
||||
#define Aig_ManForEachPi( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vPis, pObj, i )
|
||||
// iterator over the primary outputs
|
||||
#define Aig_ManForEachPo( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vPos, pObj, i )
|
||||
// iterator over all objects, including those currently not used
|
||||
#define Aig_ManForEachObj( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
|
||||
// iterator over all nodes
|
||||
#define Aig_ManForEachNode( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else
|
||||
// iterator over the nodes whose IDs are stored in the array
|
||||
#define Aig_ManForEachNodeVec( p, vIds, pObj, i ) \
|
||||
for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))); i++ )
|
||||
// iterator over the nodes in the topological order
|
||||
#define Aig_ManForEachNodeInOrder( p, pObj ) \
|
||||
for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1]; \
|
||||
p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1); \
|
||||
p->iNext = p->pOrderData[2*p->iPrev+1] )
|
||||
|
||||
// these two procedures are only here for the use inside the iterator
|
||||
static inline int Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; }
|
||||
static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; }
|
||||
// iterator over the fanouts
|
||||
#define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \
|
||||
for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \
|
||||
(((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \
|
||||
(((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ )
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// SEQUENTIAL ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// iterator over the primary inputs
|
||||
#define Aig_ManForEachPiSeq( p, pObj, i ) \
|
||||
Vec_PtrForEachEntryStop( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) )
|
||||
// iterator over the latch outputs
|
||||
#define Aig_ManForEachLoSeq( p, pObj, i ) \
|
||||
Vec_PtrForEachEntryStart( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) )
|
||||
// iterator over the primary outputs
|
||||
#define Aig_ManForEachPoSeq( p, pObj, i ) \
|
||||
Vec_PtrForEachEntryStop( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) )
|
||||
// iterator over the latch inputs
|
||||
#define Aig_ManForEachLiSeq( p, pObj, i ) \
|
||||
Vec_PtrForEachEntryStart( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) )
|
||||
// iterator over the latch input and outputs
|
||||
#define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k ) \
|
||||
for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1) \
|
||||
&& (((pObjLo)=Aig_ManLo(p, k)), 1); k++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== aigCheck.c ========================================================*/
|
||||
extern int Aig_ManCheck( Aig_Man_t * p );
|
||||
extern void Aig_ManCheckMarkA( Aig_Man_t * p );
|
||||
extern void Aig_ManCheckPhase( Aig_Man_t * p );
|
||||
/*=== aigDfs.c ==========================================================*/
|
||||
extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p );
|
||||
extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes );
|
||||
extern Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p );
|
||||
extern Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p );
|
||||
extern int Aig_ManCountLevels( Aig_Man_t * p );
|
||||
extern int Aig_DagSize( Aig_Obj_t * pObj );
|
||||
extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj );
|
||||
extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars );
|
||||
extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar );
|
||||
extern void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes );
|
||||
extern int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper );
|
||||
/*=== aigFanout.c ==========================================================*/
|
||||
extern void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout );
|
||||
extern void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout );
|
||||
extern void Aig_ManFanoutStart( Aig_Man_t * p );
|
||||
extern void Aig_ManFanoutStop( Aig_Man_t * p );
|
||||
/*=== aigMan.c ==========================================================*/
|
||||
extern Aig_Man_t * Aig_ManStart( int nNodesMax );
|
||||
extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p );
|
||||
extern Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered );
|
||||
extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 );
|
||||
extern void Aig_ManStop( Aig_Man_t * p );
|
||||
extern int Aig_ManCleanup( Aig_Man_t * p );
|
||||
extern int Aig_ManSeqCleanup( Aig_Man_t * p );
|
||||
extern void Aig_ManPrintStats( Aig_Man_t * p );
|
||||
/*=== aigMem.c ==========================================================*/
|
||||
extern void Aig_ManStartMemory( Aig_Man_t * p );
|
||||
extern void Aig_ManStopMemory( Aig_Man_t * p );
|
||||
/*=== aigMffc.c ==========================================================*/
|
||||
extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin );
|
||||
extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin );
|
||||
extern int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp );
|
||||
extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode );
|
||||
extern int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves );
|
||||
extern int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult );
|
||||
/*=== aigObj.c ==========================================================*/
|
||||
extern Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p );
|
||||
extern Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver );
|
||||
extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost );
|
||||
extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 );
|
||||
extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop );
|
||||
extern void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew );
|
||||
extern void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel );
|
||||
/*=== aigOper.c =========================================================*/
|
||||
extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i );
|
||||
extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type );
|
||||
extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
|
||||
extern Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne );
|
||||
extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
|
||||
extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
|
||||
extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 );
|
||||
extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC );
|
||||
extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs );
|
||||
extern Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 );
|
||||
extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars );
|
||||
extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars );
|
||||
extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars );
|
||||
/*=== aigOrder.c =========================================================*/
|
||||
extern void Aig_ManOrderStart( Aig_Man_t * p );
|
||||
extern void Aig_ManOrderStop( Aig_Man_t * p );
|
||||
extern void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId );
|
||||
extern void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId );
|
||||
extern void Aig_ObjOrderAdvance( Aig_Man_t * p );
|
||||
/*=== aigPart.c =========================================================*/
|
||||
extern Vec_Vec_t * Aig_ManSupports( Aig_Man_t * pMan );
|
||||
extern Vec_Vec_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Vec_t ** pvPartSupps );
|
||||
extern Vec_Vec_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize );
|
||||
/*=== aigRepr.c =========================================================*/
|
||||
extern void Aig_ManReprStart( Aig_Man_t * p, int nIdMax );
|
||||
extern void Aig_ManReprStop( Aig_Man_t * p );
|
||||
extern void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 );
|
||||
extern void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p );
|
||||
extern Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p );
|
||||
extern Aig_Man_t * Aig_ManRehash( Aig_Man_t * p );
|
||||
extern void Aig_ManCreateChoices( Aig_Man_t * p );
|
||||
/*=== aigSeq.c ========================================================*/
|
||||
extern int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits );
|
||||
/*=== aigShow.c ========================================================*/
|
||||
extern void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold );
|
||||
/*=== aigTable.c ========================================================*/
|
||||
extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost );
|
||||
extern Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 );
|
||||
extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern int Aig_TableCountEntries( Aig_Man_t * p );
|
||||
extern void Aig_TableProfile( Aig_Man_t * p );
|
||||
/*=== aigTiming.c ========================================================*/
|
||||
extern void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease );
|
||||
extern void Aig_ManStopReverseLevels( Aig_Man_t * p );
|
||||
extern void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew );
|
||||
extern void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew );
|
||||
extern void Aig_ManVerifyLevel( Aig_Man_t * p );
|
||||
extern void Aig_ManVerifyReverseLevel( Aig_Man_t * p );
|
||||
/*=== aigTruth.c ========================================================*/
|
||||
extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore );
|
||||
/*=== aigUtil.c =========================================================*/
|
||||
extern unsigned Aig_PrimeCudd( unsigned p );
|
||||
extern void Aig_ManIncrementTravId( Aig_Man_t * p );
|
||||
extern int Aig_ManLevels( Aig_Man_t * p );
|
||||
extern void Aig_ManResetRefs( Aig_Man_t * p );
|
||||
extern void Aig_ManCleanMarkA( Aig_Man_t * p );
|
||||
extern void Aig_ManCleanMarkB( Aig_Man_t * p );
|
||||
extern void Aig_ManCleanData( Aig_Man_t * p );
|
||||
extern void Aig_ObjCleanData_rec( Aig_Obj_t * pObj );
|
||||
extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper );
|
||||
extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj );
|
||||
extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 );
|
||||
extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE );
|
||||
extern Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj );
|
||||
extern void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
|
||||
extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
|
||||
extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig );
|
||||
extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig );
|
||||
extern void Aig_ManDump( Aig_Man_t * p );
|
||||
extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName );
|
||||
/*=== aigWin.c =========================================================*/
|
||||
extern void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit );
|
||||
|
||||
/*=== aigMem.c ===========================================================*/
|
||||
// fixed-size-block memory manager
|
||||
extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax );
|
||||
extern void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose );
|
||||
extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p );
|
||||
extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry );
|
||||
extern void Aig_MmFixedRestart( Aig_MmFixed_t * p );
|
||||
extern int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p );
|
||||
extern int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p );
|
||||
// flexible-size-block memory manager
|
||||
extern Aig_MmFlex_t * Aig_MmFlexStart();
|
||||
extern void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose );
|
||||
extern char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes );
|
||||
extern void Aig_MmFlexRestart( Aig_MmFlex_t * p );
|
||||
extern int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p );
|
||||
// hierarchical memory manager
|
||||
extern Aig_MmStep_t * Aig_MmStepStart( int nSteps );
|
||||
extern void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose );
|
||||
extern char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes );
|
||||
extern void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes );
|
||||
extern int Aig_MmStepReadMemUsage( Aig_MmStep_t * p );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigCheck.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [AIG checking procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigCheck.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks the consistency of the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManCheck( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pObj2;
|
||||
int i;
|
||||
// check primary inputs
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// check primary outputs
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
{
|
||||
if ( !Aig_ObjFanin0(pObj) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
if ( Aig_ObjFanin1(pObj) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// check internal nodes
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
continue;
|
||||
if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
if ( Aig_ObjFanin0(pObj)->Id >= Aig_ObjFanin1(pObj)->Id )
|
||||
{
|
||||
printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
pObj2 = Aig_TableLookup( p, pObj );
|
||||
if ( pObj2 != pObj )
|
||||
{
|
||||
printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// count the total number of nodes
|
||||
if ( Aig_ManObjNum(p) != 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The number of created nodes is wrong.\n" );
|
||||
printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n",
|
||||
1, Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p),
|
||||
1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) );
|
||||
printf( "Created = %d. Deleted = %d. Existing = %d.\n",
|
||||
p->nCreated, p->nDeleted, p->nCreated - p->nDeleted );
|
||||
return 0;
|
||||
}
|
||||
// count the number of nodes in the table
|
||||
if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) )
|
||||
{
|
||||
printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" );
|
||||
printf( "Entries = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n",
|
||||
Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p),
|
||||
Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
// if ( !Aig_ManIsAcyclic(p) )
|
||||
// return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if the markA is reset.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCheckMarkA( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
assert( pObj->fMarkA == 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks the consistency of phase assignment.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCheckPhase( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsPi(pObj) )
|
||||
assert( (int)pObj->fPhase == 0 );
|
||||
else
|
||||
assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,631 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigDfs.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [DFS traversal procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
if ( pObj == NULL )
|
||||
return;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return;
|
||||
assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) );
|
||||
Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes );
|
||||
assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManIncrementTravId( p );
|
||||
// mark constant and PIs
|
||||
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// if there are latches, mark them
|
||||
if ( Aig_ManLatchNum(p) > 0 )
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsLatch(pObj) )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// go through the nodes
|
||||
vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) )
|
||||
Aig_ManDfs_rec( p, pObj, vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( Aig_ManLatchNum(p) == 0 );
|
||||
Aig_ManIncrementTravId( p );
|
||||
// mark constant and PIs
|
||||
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// go through the nodes
|
||||
vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
|
||||
for ( i = 0; i < nNodes; i++ )
|
||||
Aig_ManDfs_rec( p, ppNodes[i], vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
if ( pObj == NULL )
|
||||
return;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return;
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes );
|
||||
Aig_ManDfsChoices_rec( p, p->pEquivs[pObj->Id], vNodes );
|
||||
assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( p->pEquivs != NULL );
|
||||
Aig_ManIncrementTravId( p );
|
||||
// mark constant and PIs
|
||||
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// go through the nodes
|
||||
vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the reverse DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
Aig_Obj_t * pFanout;
|
||||
int iFanout, i;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return;
|
||||
assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) );
|
||||
Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
|
||||
Aig_ManDfsReverse_rec( p, pFanout, vNodes );
|
||||
assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the reverse DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManIncrementTravId( p );
|
||||
// mark POs
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// if there are latches, mark them
|
||||
if ( Aig_ManLatchNum(p) > 0 )
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsLatch(pObj) )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// go through the nodes
|
||||
vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) )
|
||||
Aig_ManDfsReverse_rec( p, pObj, vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the max number of levels in the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManCountLevels( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i, LevelsMax, Level0, Level1;
|
||||
// initialize the levels
|
||||
Aig_ManConst1(p)->pData = NULL;
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = NULL;
|
||||
// compute levels in a DFS order
|
||||
vNodes = Aig_ManDfs( p );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
{
|
||||
Level0 = (int)Aig_ObjFanin0(pObj)->pData;
|
||||
Level1 = (int)Aig_ObjFanin1(pObj)->pData;
|
||||
pObj->pData = (void *)(1 + Aig_ObjIsExor(pObj) + AIG_MAX(Level0, Level1));
|
||||
}
|
||||
Vec_PtrFree( vNodes );
|
||||
// get levels of the POs
|
||||
LevelsMax = 0;
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
LevelsMax = AIG_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->pData );
|
||||
return LevelsMax;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of AIG nodes rooted at this cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ConeMark_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
|
||||
return;
|
||||
Aig_ConeMark_rec( Aig_ObjFanin0(pObj) );
|
||||
Aig_ConeMark_rec( Aig_ObjFanin1(pObj) );
|
||||
assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjSetMarkA( pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of AIG nodes rooted at this cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
|
||||
return;
|
||||
Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) );
|
||||
Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) );
|
||||
assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjSetMarkA( pObj );
|
||||
pObj->pData = NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of AIG nodes rooted at this cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
int Counter;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
|
||||
return 0;
|
||||
Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) +
|
||||
Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) );
|
||||
assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjSetMarkA( pObj );
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of AIG nodes rooted at this cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ConeUnmark_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) )
|
||||
return;
|
||||
Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) );
|
||||
Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) );
|
||||
assert( Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjClearMarkA( pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of AIG nodes rooted at this cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_DagSize( Aig_Obj_t * pObj )
|
||||
{
|
||||
int Counter;
|
||||
Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) );
|
||||
Aig_ConeUnmark_rec( Aig_Regular(pObj) );
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transfers the AIG from one manager into another.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
|
||||
return;
|
||||
Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) );
|
||||
Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) );
|
||||
pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
||||
assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjSetMarkA( pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transfers the AIG from one manager into another.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// solve simple cases
|
||||
if ( pSour == pDest )
|
||||
return pRoot;
|
||||
if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) )
|
||||
return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) );
|
||||
// set the PI mapping
|
||||
Aig_ManForEachPi( pSour, pObj, i )
|
||||
{
|
||||
if ( i == nVars )
|
||||
break;
|
||||
pObj->pData = Aig_IthVar(pDest, i);
|
||||
}
|
||||
// transfer and set markings
|
||||
Aig_Transfer_rec( pDest, Aig_Regular(pRoot) );
|
||||
// clear the markings
|
||||
Aig_ConeUnmark_rec( Aig_Regular(pRoot) );
|
||||
return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsMarkA(pObj) )
|
||||
return;
|
||||
if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) )
|
||||
{
|
||||
pObj->pData = pObj == pVar ? pFunc : pObj;
|
||||
return;
|
||||
}
|
||||
Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar );
|
||||
Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar );
|
||||
pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
||||
assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
|
||||
Aig_ObjSetMarkA( pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar )
|
||||
{
|
||||
// quit if the PI variable is not defined
|
||||
if ( iVar >= Aig_ManPiNum(p) )
|
||||
{
|
||||
printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar );
|
||||
return NULL;
|
||||
}
|
||||
// recursively perform composition
|
||||
Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManPi(p, iVar) );
|
||||
// clear the markings
|
||||
Aig_ConeUnmark_rec( Aig_Regular(pRoot) );
|
||||
return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the internal nodes of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
// Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode);
|
||||
// Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode);
|
||||
if ( pNode->fMarkA )
|
||||
return;
|
||||
pNode->fMarkA = 1;
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes );
|
||||
Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes );
|
||||
Vec_PtrPush( vNodes, pNode );
|
||||
//printf( "added %d ", pNode->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the internal nodes of the cut.]
|
||||
|
||||
Description [Does not include the leaves of the cut.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// collect and mark the leaves
|
||||
Vec_PtrClear( vNodes );
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
{
|
||||
assert( pObj->fMarkA == 0 );
|
||||
pObj->fMarkA = 1;
|
||||
// printf( "%d " , pObj->Id );
|
||||
}
|
||||
//printf( "\n" );
|
||||
// collect and mark the nodes
|
||||
Aig_ObjCollectCut_rec( pRoot, vNodes );
|
||||
// clean the nodes
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
pObj->fMarkA = 0;
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
pObj->fMarkA = 0;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes of the supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
|
||||
{
|
||||
int RetValue1, RetValue2, i;
|
||||
// check if the node is visited
|
||||
if ( Aig_Regular(pObj)->fMarkA )
|
||||
{
|
||||
// check if the node occurs in the same polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == pObj )
|
||||
return 1;
|
||||
// check if the node is present in the opposite polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == Aig_Not(pObj) )
|
||||
return -1;
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
// if the new node is complemented or a PI, another gate begins
|
||||
if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) )
|
||||
{
|
||||
Vec_PtrPush( vSuper, pObj );
|
||||
Aig_Regular(pObj)->fMarkA = 1;
|
||||
return 0;
|
||||
}
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
// go through the branches
|
||||
RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
|
||||
RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
|
||||
if ( RetValue1 == -1 || RetValue2 == -1 )
|
||||
return -1;
|
||||
// return 1 if at least one branch has a duplicate
|
||||
return RetValue1 || RetValue2;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes of the supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
|
||||
{
|
||||
int RetValue, i;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
// collect the nodes in the implication supergate
|
||||
Vec_PtrClear( vSuper );
|
||||
RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper );
|
||||
assert( Vec_PtrSize(vSuper) > 1 );
|
||||
// unmark the visited nodes
|
||||
Vec_PtrForEachEntry( vSuper, pObj, i )
|
||||
Aig_Regular(pObj)->fMarkA = 0;
|
||||
// if we found the node and its complement in the same implication supergate,
|
||||
// return empty set of nodes (meaning that we should use constant-0 node)
|
||||
if ( RetValue == -1 )
|
||||
vSuper->nSize = 0;
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigFanout.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Fanout manipulation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
// 0: first iFan
|
||||
// 1: prev iFan0
|
||||
// 2: prev iFan1
|
||||
// 3: next iFan0
|
||||
// 4: next iFan1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline int Aig_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; }
|
||||
static inline int * Aig_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; }
|
||||
static inline int * Aig_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); }
|
||||
static inline int * Aig_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create fanout for all objects in the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManFanoutStart( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( Aig_ManBufNum(p) == 0 );
|
||||
// allocate fanout datastructure
|
||||
assert( p->pFanData == NULL );
|
||||
p->nFansAlloc = 2 * Aig_ManObjIdMax(p);
|
||||
if ( p->nFansAlloc < (1<<12) )
|
||||
p->nFansAlloc = (1<<12);
|
||||
p->pFanData = ALLOC( int, 5 * p->nFansAlloc );
|
||||
memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc );
|
||||
// add fanouts for all objects
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjChild0(pObj) )
|
||||
Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
|
||||
if ( Aig_ObjChild1(pObj) )
|
||||
Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deletes fanout for all objects in the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManFanoutStop( Aig_Man_t * p )
|
||||
{
|
||||
assert( p->pFanData != NULL );
|
||||
FREE( p->pFanData );
|
||||
p->nFansAlloc = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds fanout (pFanout) of node (pObj).]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout )
|
||||
{
|
||||
int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
|
||||
assert( p->pFanData );
|
||||
assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) );
|
||||
assert( pFanout->Id > 0 );
|
||||
if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc )
|
||||
{
|
||||
int nFansAlloc = 2 * AIG_MAX( pObj->Id, pFanout->Id );
|
||||
p->pFanData = REALLOC( int, p->pFanData, 5 * nFansAlloc );
|
||||
memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) );
|
||||
p->nFansAlloc = nFansAlloc;
|
||||
}
|
||||
assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc );
|
||||
iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) );
|
||||
pPrevC = Aig_FanoutPrev( p->pFanData, iFan );
|
||||
pNextC = Aig_FanoutNext( p->pFanData, iFan );
|
||||
pFirst = Aig_FanoutObj( p->pFanData, pObj->Id );
|
||||
if ( *pFirst == 0 )
|
||||
{
|
||||
*pFirst = iFan;
|
||||
*pPrevC = iFan;
|
||||
*pNextC = iFan;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrev = Aig_FanoutPrev( p->pFanData, *pFirst );
|
||||
pNext = Aig_FanoutNext( p->pFanData, *pPrev );
|
||||
assert( *pNext == *pFirst );
|
||||
*pPrevC = *pPrev;
|
||||
*pNextC = *pFirst;
|
||||
*pPrev = iFan;
|
||||
*pNext = iFan;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Removes fanout (pFanout) of node (pObj).]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout )
|
||||
{
|
||||
int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
|
||||
assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc );
|
||||
assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) );
|
||||
assert( pFanout->Id > 0 );
|
||||
iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) );
|
||||
pPrevC = Aig_FanoutPrev( p->pFanData, iFan );
|
||||
pNextC = Aig_FanoutNext( p->pFanData, iFan );
|
||||
pPrev = Aig_FanoutPrev( p->pFanData, *pNextC );
|
||||
pNext = Aig_FanoutNext( p->pFanData, *pPrevC );
|
||||
assert( *pPrev == iFan );
|
||||
assert( *pNext == iFan );
|
||||
pFirst = Aig_FanoutObj( p->pFanData, pObj->Id );
|
||||
assert( *pFirst > 0 );
|
||||
if ( *pFirst == iFan )
|
||||
{
|
||||
if ( *pNextC == iFan )
|
||||
{
|
||||
*pFirst = 0;
|
||||
*pPrev = 0;
|
||||
*pNext = 0;
|
||||
*pPrevC = 0;
|
||||
*pNextC = 0;
|
||||
return;
|
||||
}
|
||||
*pFirst = *pNextC;
|
||||
}
|
||||
*pPrev = *pPrevC;
|
||||
*pNext = *pNextC;
|
||||
*pPrevC = 0;
|
||||
*pNextC = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [AIG manager.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the AIG manager.]
|
||||
|
||||
Description [The argument of this procedure is a soft limit on the
|
||||
the number of nodes, or 0 if the limit is unknown.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManStart( int nNodesMax )
|
||||
{
|
||||
Aig_Man_t * p;
|
||||
if ( nNodesMax <= 0 )
|
||||
nNodesMax = 10007;
|
||||
// start the manager
|
||||
p = ALLOC( Aig_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Aig_Man_t) );
|
||||
// perform initializations
|
||||
p->nTravIds = 1;
|
||||
p->fCatchExor = 0;
|
||||
// allocate arrays for nodes
|
||||
p->vPis = Vec_PtrAlloc( 100 );
|
||||
p->vPos = Vec_PtrAlloc( 100 );
|
||||
p->vObjs = Vec_PtrAlloc( 1000 );
|
||||
p->vBufs = Vec_PtrAlloc( 100 );
|
||||
// prepare the internal memory manager
|
||||
p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax );
|
||||
// create the constant node
|
||||
p->pConst1 = Aig_ManFetchMemory( p );
|
||||
p->pConst1->Type = AIG_OBJ_CONST1;
|
||||
p->pConst1->fPhase = 1;
|
||||
p->nObjs[AIG_OBJ_CONST1]++;
|
||||
// start the table
|
||||
p->nTableSize = Aig_PrimeCudd( nNodesMax );
|
||||
p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize );
|
||||
memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// create the new manager
|
||||
pNew = Aig_ManStart( Aig_ManObjIdMax(p) + 1 );
|
||||
// create the PIs
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = Aig_ObjCreatePi(pNew);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates the AIG manager recursively.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
if ( pObj->pData )
|
||||
return pObj->pData;
|
||||
Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) );
|
||||
if ( Aig_ObjIsBuf(pObj) )
|
||||
return pObj->pData = Aig_ObjChild0Copy(pObj);
|
||||
Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) );
|
||||
return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// create the new manager
|
||||
pNew = Aig_ManStart( Aig_ManObjIdMax(p) + 1 );
|
||||
pNew->nRegs = p->nRegs;
|
||||
pNew->nAsserts = p->nAsserts;
|
||||
// create the PIs
|
||||
Aig_ManCleanData( p );
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = Aig_ObjCreatePi(pNew);
|
||||
// duplicate internal nodes
|
||||
if ( fOrdered )
|
||||
{
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( Aig_ObjIsBuf(pObj) )
|
||||
pObj->pData = Aig_ObjChild0Copy(pObj);
|
||||
else if ( Aig_ObjIsNode(pObj) )
|
||||
pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
if ( !Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
Aig_ManDup_rec( pNew, p, pObj );
|
||||
assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level );
|
||||
}
|
||||
}
|
||||
// add the POs
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
|
||||
assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
|
||||
// check the resulting network
|
||||
if ( !Aig_ManCheck(pNew) )
|
||||
printf( "Aig_ManDup(): The check has failed.\n" );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Extracts the miter composed of XOR of the two nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// create the new manager
|
||||
pNew = Aig_ManStart( Aig_ManObjIdMax(p) + 1 );
|
||||
// create the PIs
|
||||
Aig_ManCleanData( p );
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = Aig_ObjCreatePi(pNew);
|
||||
// dump the nodes
|
||||
Aig_ManDup_rec( pNew, p, pNode1 );
|
||||
Aig_ManDup_rec( pNew, p, pNode2 );
|
||||
// construct the EXOR
|
||||
pObj = Aig_Exor( pNew, pNode1->pData, pNode2->pData );
|
||||
pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) );
|
||||
// add the PO
|
||||
Aig_ObjCreatePo( pNew, pObj );
|
||||
// check the resulting network
|
||||
if ( !Aig_ManCheck(pNew) )
|
||||
printf( "Aig_ManDup(): The check has failed.\n" );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManStop( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// print time
|
||||
if ( p->time1 ) { PRT( "time1", p->time1 ); }
|
||||
if ( p->time2 ) { PRT( "time2", p->time2 ); }
|
||||
// delete fanout
|
||||
if ( p->pFanData )
|
||||
Aig_ManFanoutStop( p );
|
||||
// make sure the nodes have clean marks
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
assert( !pObj->fMarkA && !pObj->fMarkB );
|
||||
// Aig_TableProfile( p );
|
||||
Aig_MmFixedStop( p->pMemObjs, 0 );
|
||||
if ( p->vPis ) Vec_PtrFree( p->vPis );
|
||||
if ( p->vPos ) Vec_PtrFree( p->vPos );
|
||||
if ( p->vObjs ) Vec_PtrFree( p->vObjs );
|
||||
if ( p->vBufs ) Vec_PtrFree( p->vBufs );
|
||||
if ( p->vLevelR ) Vec_IntFree( p->vLevelR );
|
||||
if ( p->vLevels ) Vec_VecFree( p->vLevels );
|
||||
FREE( p->pReprs );
|
||||
FREE( p->pEquivs );
|
||||
free( p->pTable );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of dangling nodes removed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return;
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
// collect latch input corresponding to unmarked PI (latch output)
|
||||
if ( Aig_ObjIsPi(pObj) )
|
||||
{
|
||||
Vec_PtrPush( vNodes, pObj->pNext );
|
||||
return;
|
||||
}
|
||||
if ( Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
return;
|
||||
}
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of dangling nodes removed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManSeqCleanup( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes, * vCis, * vCos;
|
||||
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
|
||||
int i, nTruePis, nTruePos;
|
||||
assert( Aig_ManBufNum(p) == 0 );
|
||||
|
||||
// mark the PIs
|
||||
Aig_ManIncrementTravId( p );
|
||||
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
|
||||
Aig_ManForEachPiSeq( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
|
||||
// prepare to collect nodes reachable from POs
|
||||
vNodes = Vec_PtrAlloc( 100 );
|
||||
Aig_ManForEachPoSeq( p, pObj, i )
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
|
||||
// remember latch inputs in latch outputs
|
||||
Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
|
||||
pObjLo->pNext = pObjLi;
|
||||
// mark the nodes reachable from these nodes
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
Aig_ManSeqCleanup_rec( p, pObj, vNodes );
|
||||
assert( Vec_PtrSize(vNodes) <= Aig_ManPoNum(p) );
|
||||
// clean latch output pointers
|
||||
Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
|
||||
pObjLo->pNext = NULL;
|
||||
|
||||
// if some latches are removed, update PIs/POs
|
||||
if ( Vec_PtrSize(vNodes) < Aig_ManPoNum(p) )
|
||||
{
|
||||
// collect new CIs/COs
|
||||
vCis = Vec_PtrAlloc( Aig_ManPiNum(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
Vec_PtrPush( vCis, pObj );
|
||||
vCos = Vec_PtrAlloc( Aig_ManPoNum(p) );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
Vec_PtrPush( vCos, pObj );
|
||||
else
|
||||
Aig_ObjDisconnect( p, pObj );
|
||||
// remember the number of true PIs/POs
|
||||
nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
|
||||
nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
|
||||
// set the new number of registers
|
||||
p->nRegs -= Aig_ManPoNum(p) - Vec_PtrSize(vNodes);
|
||||
// create new PIs/POs
|
||||
assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs );
|
||||
assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs );
|
||||
Vec_PtrFree( p->vPis ); p->vPis = vCis;
|
||||
Vec_PtrFree( p->vPos ); p->vPos = vCos;
|
||||
p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis );
|
||||
p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos );
|
||||
}
|
||||
Vec_PtrFree( vNodes );
|
||||
// remove dangling nodes
|
||||
return Aig_ManCleanup( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of dangling nodes removed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManCleanup( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vObjs;
|
||||
Aig_Obj_t * pNode;
|
||||
int i, nNodesOld;
|
||||
nNodesOld = Aig_ManNodeNum(p);
|
||||
// collect roots of dangling nodes
|
||||
vObjs = Vec_PtrAlloc( 100 );
|
||||
Aig_ManForEachObj( p, pNode, i )
|
||||
if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 )
|
||||
Vec_PtrPush( vObjs, pNode );
|
||||
// recursively remove dangling nodes
|
||||
Vec_PtrForEachEntry( vObjs, pNode, i )
|
||||
Aig_ObjDelete_rec( p, pNode, 1 );
|
||||
Vec_PtrFree( vObjs );
|
||||
return nNodesOld - Aig_ManNodeNum(p);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManPrintStats( Aig_Man_t * p )
|
||||
{
|
||||
printf( "PI/PO/Lat = %5d/%5d/%5d ", Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManLatchNum(p) );
|
||||
printf( "A = %7d. ", Aig_ManAndNum(p) );
|
||||
if ( Aig_ManExorNum(p) )
|
||||
printf( "X = %5d. ", Aig_ManExorNum(p) );
|
||||
// if ( Aig_ManBufNum(p) )
|
||||
printf( "B = %5d. ", Aig_ManBufNum(p) );
|
||||
// printf( "Cre = %6d. ", p->nCreated );
|
||||
// printf( "Del = %6d. ", p->nDeleted );
|
||||
// printf( "Lev = %3d. ", Aig_ManCountLevels(p) );
|
||||
printf( "Max = %7d. ", Aig_ManObjIdMax(p) );
|
||||
printf( "Lev = %3d. ", Aig_ManLevels(p) );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,598 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigMem.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Memory managers.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Aig_MmFixed_t_
|
||||
{
|
||||
// information about individual entries
|
||||
int nEntrySize; // the size of one entry
|
||||
int nEntriesAlloc; // the total number of entries allocated
|
||||
int nEntriesUsed; // the number of entries in use
|
||||
int nEntriesMax; // the max number of entries in use
|
||||
char * pEntriesFree; // the linked list of free entries
|
||||
|
||||
// this is where the memory is stored
|
||||
int nChunkSize; // the size of one chunk
|
||||
int nChunksAlloc; // the maximum number of memory chunks
|
||||
int nChunks; // the current number of memory chunks
|
||||
char ** pChunks; // the allocated memory
|
||||
|
||||
// statistics
|
||||
int nMemoryUsed; // memory used in the allocated entries
|
||||
int nMemoryAlloc; // memory allocated
|
||||
};
|
||||
|
||||
struct Aig_MmFlex_t_
|
||||
{
|
||||
// information about individual entries
|
||||
int nEntriesUsed; // the number of entries allocated
|
||||
char * pCurrent; // the current pointer to free memory
|
||||
char * pEnd; // the first entry outside the free memory
|
||||
|
||||
// this is where the memory is stored
|
||||
int nChunkSize; // the size of one chunk
|
||||
int nChunksAlloc; // the maximum number of memory chunks
|
||||
int nChunks; // the current number of memory chunks
|
||||
char ** pChunks; // the allocated memory
|
||||
|
||||
// statistics
|
||||
int nMemoryUsed; // memory used in the allocated entries
|
||||
int nMemoryAlloc; // memory allocated
|
||||
};
|
||||
|
||||
struct Aig_MmStep_t_
|
||||
{
|
||||
int nMems; // the number of fixed memory managers employed
|
||||
Aig_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
|
||||
int nMapSize; // the size of the memory array
|
||||
Aig_MmFixed_t ** pMap; // maps the number of bytes into its memory manager
|
||||
};
|
||||
|
||||
#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
|
||||
#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
|
||||
#define REALLOC(type, obj, num) \
|
||||
((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
|
||||
((type *) malloc(sizeof(type) * (num))))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates memory pieces of fixed size.]
|
||||
|
||||
Description [The size of the chunk is computed as the minimum of
|
||||
1024 entries and 64K. Can only work with entry size at least 4 byte long.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax )
|
||||
{
|
||||
Aig_MmFixed_t * p;
|
||||
|
||||
p = ALLOC( Aig_MmFixed_t, 1 );
|
||||
memset( p, 0, sizeof(Aig_MmFixed_t) );
|
||||
|
||||
p->nEntrySize = nEntrySize;
|
||||
p->nEntriesAlloc = 0;
|
||||
p->nEntriesUsed = 0;
|
||||
p->pEntriesFree = NULL;
|
||||
|
||||
p->nChunkSize = nEntriesMax / 8;
|
||||
if ( p->nChunkSize < 8 )
|
||||
p->nChunkSize = 8;
|
||||
|
||||
p->nChunksAlloc = 64;
|
||||
p->nChunks = 0;
|
||||
p->pChunks = ALLOC( char *, p->nChunksAlloc );
|
||||
|
||||
p->nMemoryUsed = 0;
|
||||
p->nMemoryAlloc = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose )
|
||||
{
|
||||
int i;
|
||||
if ( p == NULL )
|
||||
return;
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
|
||||
p->nEntrySize, p->nChunkSize, p->nChunks );
|
||||
printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
|
||||
p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
|
||||
}
|
||||
for ( i = 0; i < p->nChunks; i++ )
|
||||
free( p->pChunks[i] );
|
||||
free( p->pChunks );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p )
|
||||
{
|
||||
char * pTemp;
|
||||
int i;
|
||||
|
||||
// check if there are still free entries
|
||||
if ( p->nEntriesUsed == p->nEntriesAlloc )
|
||||
{ // need to allocate more entries
|
||||
assert( p->pEntriesFree == NULL );
|
||||
if ( p->nChunks == p->nChunksAlloc )
|
||||
{
|
||||
p->nChunksAlloc *= 2;
|
||||
p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
|
||||
}
|
||||
p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize );
|
||||
p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
|
||||
// transform these entries into a linked list
|
||||
pTemp = p->pEntriesFree;
|
||||
for ( i = 1; i < p->nChunkSize; i++ )
|
||||
{
|
||||
*((char **)pTemp) = pTemp + p->nEntrySize;
|
||||
pTemp += p->nEntrySize;
|
||||
}
|
||||
// set the last link
|
||||
*((char **)pTemp) = NULL;
|
||||
// add the chunk to the chunk storage
|
||||
p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
|
||||
// add to the number of entries allocated
|
||||
p->nEntriesAlloc += p->nChunkSize;
|
||||
}
|
||||
// incrememt the counter of used entries
|
||||
p->nEntriesUsed++;
|
||||
if ( p->nEntriesMax < p->nEntriesUsed )
|
||||
p->nEntriesMax = p->nEntriesUsed;
|
||||
// return the first entry in the free entry list
|
||||
pTemp = p->pEntriesFree;
|
||||
p->pEntriesFree = *((char **)pTemp);
|
||||
return pTemp;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry )
|
||||
{
|
||||
// decrement the counter of used entries
|
||||
p->nEntriesUsed--;
|
||||
// add the entry to the linked list of free entries
|
||||
*((char **)pEntry) = p->pEntriesFree;
|
||||
p->pEntriesFree = pEntry;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description [Relocates all the memory except the first chunk.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmFixedRestart( Aig_MmFixed_t * p )
|
||||
{
|
||||
int i;
|
||||
char * pTemp;
|
||||
if ( p->nChunks == 0 )
|
||||
return;
|
||||
// deallocate all chunks except the first one
|
||||
for ( i = 1; i < p->nChunks; i++ )
|
||||
free( p->pChunks[i] );
|
||||
p->nChunks = 1;
|
||||
// transform these entries into a linked list
|
||||
pTemp = p->pChunks[0];
|
||||
for ( i = 1; i < p->nChunkSize; i++ )
|
||||
{
|
||||
*((char **)pTemp) = pTemp + p->nEntrySize;
|
||||
pTemp += p->nEntrySize;
|
||||
}
|
||||
// set the last link
|
||||
*((char **)pTemp) = NULL;
|
||||
// set the free entry list
|
||||
p->pEntriesFree = p->pChunks[0];
|
||||
// set the correct statistics
|
||||
p->nMemoryAlloc = p->nEntrySize * p->nChunkSize;
|
||||
p->nMemoryUsed = 0;
|
||||
p->nEntriesAlloc = p->nChunkSize;
|
||||
p->nEntriesUsed = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p )
|
||||
{
|
||||
return p->nMemoryAlloc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p )
|
||||
{
|
||||
return p->nEntriesMax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates entries of flexible size.]
|
||||
|
||||
Description [Can only work with entry size at least 4 byte long.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_MmFlex_t * Aig_MmFlexStart()
|
||||
{
|
||||
Aig_MmFlex_t * p;
|
||||
|
||||
p = ALLOC( Aig_MmFlex_t, 1 );
|
||||
memset( p, 0, sizeof(Aig_MmFlex_t) );
|
||||
|
||||
p->nEntriesUsed = 0;
|
||||
p->pCurrent = NULL;
|
||||
p->pEnd = NULL;
|
||||
|
||||
p->nChunkSize = (1 << 18);
|
||||
p->nChunksAlloc = 64;
|
||||
p->nChunks = 0;
|
||||
p->pChunks = ALLOC( char *, p->nChunksAlloc );
|
||||
|
||||
p->nMemoryUsed = 0;
|
||||
p->nMemoryAlloc = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose )
|
||||
{
|
||||
int i;
|
||||
if ( p == NULL )
|
||||
return;
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
|
||||
p->nChunkSize, p->nChunks );
|
||||
printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
|
||||
p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
|
||||
}
|
||||
for ( i = 0; i < p->nChunks; i++ )
|
||||
free( p->pChunks[i] );
|
||||
free( p->pChunks );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes )
|
||||
{
|
||||
char * pTemp;
|
||||
// check if there are still free entries
|
||||
if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
|
||||
{ // need to allocate more entries
|
||||
if ( p->nChunks == p->nChunksAlloc )
|
||||
{
|
||||
p->nChunksAlloc *= 2;
|
||||
p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
|
||||
}
|
||||
if ( nBytes > p->nChunkSize )
|
||||
{
|
||||
// resize the chunk size if more memory is requested than it can give
|
||||
// (ideally, this should never happen)
|
||||
p->nChunkSize = 2 * nBytes;
|
||||
}
|
||||
p->pCurrent = ALLOC( char, p->nChunkSize );
|
||||
p->pEnd = p->pCurrent + p->nChunkSize;
|
||||
p->nMemoryAlloc += p->nChunkSize;
|
||||
// add the chunk to the chunk storage
|
||||
p->pChunks[ p->nChunks++ ] = p->pCurrent;
|
||||
}
|
||||
assert( p->pCurrent + nBytes <= p->pEnd );
|
||||
// increment the counter of used entries
|
||||
p->nEntriesUsed++;
|
||||
// keep track of the memory used
|
||||
p->nMemoryUsed += nBytes;
|
||||
// return the next entry
|
||||
pTemp = p->pCurrent;
|
||||
p->pCurrent += nBytes;
|
||||
return pTemp;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description [Relocates all the memory except the first chunk.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmFlexRestart( Aig_MmFlex_t * p )
|
||||
{
|
||||
int i;
|
||||
if ( p->nChunks == 0 )
|
||||
return;
|
||||
// deallocate all chunks except the first one
|
||||
for ( i = 1; i < p->nChunks; i++ )
|
||||
free( p->pChunks[i] );
|
||||
p->nChunks = 1;
|
||||
p->nMemoryAlloc = p->nChunkSize;
|
||||
// transform these entries into a linked list
|
||||
p->pCurrent = p->pChunks[0];
|
||||
p->pEnd = p->pCurrent + p->nChunkSize;
|
||||
p->nEntriesUsed = 0;
|
||||
p->nMemoryUsed = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p )
|
||||
{
|
||||
return p->nMemoryUsed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the hierarchical memory manager.]
|
||||
|
||||
Description [This manager can allocate entries of any size.
|
||||
Iternally they are mapped into the entries with the number of bytes
|
||||
equal to the power of 2. The smallest entry size is 8 bytes. The
|
||||
next one is 16 bytes etc. So, if the user requests 6 bytes, he gets
|
||||
8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
|
||||
The input parameters "nSteps" says how many fixed memory managers
|
||||
are employed internally. Calling this procedure with nSteps equal
|
||||
to 10 results in 10 hierarchically arranged internal memory managers,
|
||||
which can allocate up to 4096 (1Kb) entries. Requests for larger
|
||||
entries are handed over to malloc() and then free()ed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_MmStep_t * Aig_MmStepStart( int nSteps )
|
||||
{
|
||||
Aig_MmStep_t * p;
|
||||
int i, k;
|
||||
p = ALLOC( Aig_MmStep_t, 1 );
|
||||
memset( p, 0, sizeof(Aig_MmStep_t) );
|
||||
p->nMems = nSteps;
|
||||
// start the fixed memory managers
|
||||
p->pMems = ALLOC( Aig_MmFixed_t *, p->nMems );
|
||||
for ( i = 0; i < p->nMems; i++ )
|
||||
p->pMems[i] = Aig_MmFixedStart( (8<<i), (1<<13) );
|
||||
// set up the mapping of the required memory size into the corresponding manager
|
||||
p->nMapSize = (4<<p->nMems);
|
||||
p->pMap = ALLOC( Aig_MmFixed_t *, p->nMapSize+1 );
|
||||
p->pMap[0] = NULL;
|
||||
for ( k = 1; k <= 4; k++ )
|
||||
p->pMap[k] = p->pMems[0];
|
||||
for ( i = 0; i < p->nMems; i++ )
|
||||
for ( k = (4<<i)+1; k <= (8<<i); k++ )
|
||||
p->pMap[k] = p->pMems[i];
|
||||
//for ( i = 1; i < 100; i ++ )
|
||||
//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the memory manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < p->nMems; i++ )
|
||||
Aig_MmFixedStop( p->pMems[i], fVerbose );
|
||||
// if ( p->pLargeChunks )
|
||||
// {
|
||||
// for ( i = 0; i < p->nLargeChunks; i++ )
|
||||
// free( p->pLargeChunks[i] );
|
||||
// free( p->pLargeChunks );
|
||||
// }
|
||||
free( p->pMems );
|
||||
free( p->pMap );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates the entry.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes )
|
||||
{
|
||||
if ( nBytes == 0 )
|
||||
return NULL;
|
||||
if ( nBytes > p->nMapSize )
|
||||
{
|
||||
// printf( "Allocating %d bytes.\n", nBytes );
|
||||
/*
|
||||
if ( p->nLargeChunks == p->nLargeChunksAlloc )
|
||||
{
|
||||
if ( p->nLargeChunksAlloc == 0 )
|
||||
p->nLargeChunksAlloc = 5;
|
||||
p->nLargeChunksAlloc *= 2;
|
||||
p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc );
|
||||
}
|
||||
p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes );
|
||||
return p->pLargeChunks[ p->nLargeChunks - 1 ];
|
||||
*/
|
||||
return ALLOC( char, nBytes );
|
||||
}
|
||||
return Aig_MmFixedEntryFetch( p->pMap[nBytes] );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recycles the entry.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes )
|
||||
{
|
||||
if ( nBytes == 0 )
|
||||
return;
|
||||
if ( nBytes > p->nMapSize )
|
||||
{
|
||||
free( pEntry );
|
||||
return;
|
||||
}
|
||||
Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_MmStepReadMemUsage( Aig_MmStep_t * p )
|
||||
{
|
||||
int i, nMemTotal = 0;
|
||||
for ( i = 0; i < p->nMems; i++ )
|
||||
nMemTotal += p->pMems[i]->nMemoryAlloc;
|
||||
return nMemTotal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,297 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigMffc.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Computation of MFFCs.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Dereferences the node's MFFC.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin )
|
||||
{
|
||||
Aig_Obj_t * pFanin;
|
||||
int Counter = 0;
|
||||
if ( Aig_ObjIsPi(pNode) )
|
||||
return 0;
|
||||
// consider the first fanin
|
||||
pFanin = Aig_ObjFanin0(pNode);
|
||||
assert( pFanin->nRefs > 0 );
|
||||
if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeDeref_rec( pFanin, LevelMin );
|
||||
// skip the buffer
|
||||
if ( Aig_ObjIsBuf(pNode) )
|
||||
return Counter;
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
// consider the second fanin
|
||||
pFanin = Aig_ObjFanin1(pNode);
|
||||
assert( pFanin->nRefs > 0 );
|
||||
if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeDeref_rec( pFanin, LevelMin );
|
||||
return Counter + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [References the node's MFFC.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin )
|
||||
{
|
||||
Aig_Obj_t * pFanin;
|
||||
int Counter = 0;
|
||||
if ( Aig_ObjIsPi(pNode) )
|
||||
return 0;
|
||||
// consider the first fanin
|
||||
pFanin = Aig_ObjFanin0(pNode);
|
||||
if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeRef_rec( pFanin, LevelMin );
|
||||
// skip the buffer
|
||||
if ( Aig_ObjIsBuf(pNode) )
|
||||
return Counter;
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
// consider the second fanin
|
||||
pFanin = Aig_ObjFanin1(pNode);
|
||||
if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeRef_rec( pFanin, LevelMin );
|
||||
return Counter + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [References the node's MFFC.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin )
|
||||
{
|
||||
Aig_Obj_t * pFanin;
|
||||
int Counter = 0;
|
||||
if ( Aig_ObjIsPi(pNode) )
|
||||
return 0;
|
||||
Aig_ObjSetTravIdCurrent( p, pNode );
|
||||
// consider the first fanin
|
||||
pFanin = Aig_ObjFanin0(pNode);
|
||||
if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin );
|
||||
if ( Aig_ObjIsBuf(pNode) )
|
||||
return Counter;
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
// consider the second fanin
|
||||
pFanin = Aig_ObjFanin1(pNode);
|
||||
if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
|
||||
Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin );
|
||||
return Counter + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the internal and boundary nodes in the derefed MFFC.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_NodeMffsSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip )
|
||||
{
|
||||
// skip visited nodes
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pNode) )
|
||||
return;
|
||||
Aig_ObjSetTravIdCurrent(p, pNode);
|
||||
// add to the new support nodes
|
||||
if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsPi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) )
|
||||
{
|
||||
if ( vSupp ) Vec_PtrPush( vSupp, pNode );
|
||||
return;
|
||||
}
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
// recur on the children
|
||||
Aig_NodeMffsSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip );
|
||||
Aig_NodeMffsSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the support of depth-limited MFFC.]
|
||||
|
||||
Description [Returns the number of internal nodes in the MFFC.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp )
|
||||
{
|
||||
int ConeSize1, ConeSize2;
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
if ( vSupp ) Vec_PtrClear( vSupp );
|
||||
Aig_ManIncrementTravId( p );
|
||||
ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin );
|
||||
Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL );
|
||||
ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin );
|
||||
assert( ConeSize1 == ConeSize2 );
|
||||
assert( ConeSize1 > 0 );
|
||||
return ConeSize1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Labels the nodes in the MFFC.]
|
||||
|
||||
Description [Returns the number of internal nodes in the MFFC.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode )
|
||||
{
|
||||
int ConeSize1, ConeSize2;
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
Aig_ManIncrementTravId( p );
|
||||
ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
|
||||
ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
|
||||
assert( ConeSize1 == ConeSize2 );
|
||||
assert( ConeSize1 > 0 );
|
||||
return ConeSize1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Labels the nodes in the MFFC.]
|
||||
|
||||
Description [Returns the number of internal nodes in the MFFC.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i, ConeSize1, ConeSize2;
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( Aig_ObjIsNode(pNode) );
|
||||
Aig_ManIncrementTravId( p );
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
pObj->nRefs++;
|
||||
ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
|
||||
ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
pObj->nRefs--;
|
||||
assert( ConeSize1 == ConeSize2 );
|
||||
assert( ConeSize1 > 0 );
|
||||
return ConeSize1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Expands the cut by adding the most closely related node.]
|
||||
|
||||
Description [Returns 1 if the cut exists.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pLeafBest;
|
||||
int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest;
|
||||
// dereference the current cut
|
||||
LevelMax = 0;
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
LevelMax = AIG_MAX( LevelMax, (int)pObj->Level );
|
||||
if ( LevelMax == 0 )
|
||||
return 0;
|
||||
// dereference the cut
|
||||
ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
|
||||
// try expanding each node in the boundary
|
||||
ConeBest = AIG_INFINITY;
|
||||
pLeafBest = NULL;
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
{
|
||||
if ( (int)pObj->Level != LevelMax )
|
||||
continue;
|
||||
ConeCur1 = Aig_NodeDeref_rec( pObj, 0 );
|
||||
if ( ConeBest > ConeCur1 )
|
||||
{
|
||||
ConeBest = ConeCur1;
|
||||
pLeafBest = pObj;
|
||||
}
|
||||
ConeCur2 = Aig_NodeRef_rec( pObj, 0 );
|
||||
assert( ConeCur1 == ConeCur2 );
|
||||
}
|
||||
assert( pLeafBest != NULL );
|
||||
assert( Aig_ObjIsNode(pLeafBest) );
|
||||
// deref the best leaf
|
||||
ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 );
|
||||
// collect the cut nodes
|
||||
Vec_PtrClear( vResult );
|
||||
Aig_ManIncrementTravId( p );
|
||||
Aig_NodeMffsSupp_rec( p, pNode, 0, vResult, 1, pLeafBest );
|
||||
// ref the nodes
|
||||
ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 );
|
||||
assert( ConeCur1 == ConeCur2 );
|
||||
// ref the original node
|
||||
ConeSize2 = Aig_NodeRef_rec( pNode, 0 );
|
||||
assert( ConeSize1 == ConeSize2 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigObj.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Adding/removing objects.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates primary input.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
pObj = Aig_ManFetchMemory( p );
|
||||
pObj->Type = AIG_OBJ_PI;
|
||||
Vec_PtrPush( p->vPis, pObj );
|
||||
p->nObjs[AIG_OBJ_PI]++;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates primary output with the given driver.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
pObj = Aig_ManFetchMemory( p );
|
||||
pObj->Type = AIG_OBJ_PO;
|
||||
Vec_PtrPush( p->vPos, pObj );
|
||||
Aig_ObjConnect( p, pObj, pDriver, NULL );
|
||||
p->nObjs[AIG_OBJ_PO]++;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create the new node assuming it does not exist.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
assert( !Aig_IsComplement(pGhost) );
|
||||
assert( Aig_ObjIsHash(pGhost) );
|
||||
assert( pGhost == &p->Ghost );
|
||||
// get memory for the new object
|
||||
pObj = Aig_ManFetchMemory( p );
|
||||
pObj->Type = pGhost->Type;
|
||||
// add connections
|
||||
Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
|
||||
// update node counters of the manager
|
||||
p->nObjs[Aig_ObjType(pObj)]++;
|
||||
assert( pObj->pData == NULL );
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Connect the object to the fanin.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( !Aig_ObjIsPi(pObj) );
|
||||
// add the first fanin
|
||||
pObj->pFanin0 = pFan0;
|
||||
pObj->pFanin1 = pFan1;
|
||||
// increment references of the fanins and add their fanouts
|
||||
if ( pFan0 != NULL )
|
||||
{
|
||||
assert( Aig_ObjFanin0(pObj)->Type > 0 );
|
||||
Aig_ObjRef( Aig_ObjFanin0(pObj) );
|
||||
if ( p->pFanData )
|
||||
Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
|
||||
}
|
||||
if ( pFan1 != NULL )
|
||||
{
|
||||
assert( Aig_ObjFanin1(pObj)->Type > 0 );
|
||||
Aig_ObjRef( Aig_ObjFanin1(pObj) );
|
||||
if ( p->pFanData )
|
||||
Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj );
|
||||
}
|
||||
// set level and phase
|
||||
pObj->Level = Aig_ObjLevelNew( pObj );
|
||||
pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1);
|
||||
// add the node to the structural hash table
|
||||
if ( Aig_ObjIsHash(pObj) )
|
||||
Aig_TableInsert( p, pObj );
|
||||
// add the node to the dynamically updated topological order
|
||||
if ( p->pOrderData && Aig_ObjIsNode(pObj) )
|
||||
Aig_ObjOrderInsert( p, pObj->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Disconnects the object from the fanins.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
// remove connections
|
||||
if ( pObj->pFanin0 != NULL )
|
||||
{
|
||||
if ( p->pFanData )
|
||||
Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj );
|
||||
Aig_ObjDeref(Aig_ObjFanin0(pObj));
|
||||
}
|
||||
if ( pObj->pFanin1 != NULL )
|
||||
{
|
||||
if ( p->pFanData )
|
||||
Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj );
|
||||
Aig_ObjDeref(Aig_ObjFanin1(pObj));
|
||||
}
|
||||
// remove the node from the structural hash table
|
||||
if ( Aig_ObjIsHash(pObj) )
|
||||
Aig_TableDelete( p, pObj );
|
||||
// add the first fanin
|
||||
pObj->pFanin0 = NULL;
|
||||
pObj->pFanin1 = NULL;
|
||||
// remove the node from the dynamically updated topological order
|
||||
if ( p->pOrderData && Aig_ObjIsNode(pObj) )
|
||||
Aig_ObjOrderRemove( p, pObj->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deletes the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( !Aig_ObjIsTerm(pObj) );
|
||||
assert( Aig_ObjRefs(pObj) == 0 );
|
||||
if ( p->pFanData && Aig_ObjIsBuf(pObj) )
|
||||
Vec_PtrRemove( p->vBufs, pObj );
|
||||
p->nObjs[pObj->Type]--;
|
||||
Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
|
||||
Aig_ManRecycleMemory( p, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deletes the MFFC of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop )
|
||||
{
|
||||
Aig_Obj_t * pFanin0, * pFanin1;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) )
|
||||
return;
|
||||
assert( !Aig_ObjIsPo(pObj) );
|
||||
pFanin0 = Aig_ObjFanin0(pObj);
|
||||
pFanin1 = Aig_ObjFanin1(pObj);
|
||||
Aig_ObjDisconnect( p, pObj );
|
||||
if ( fFreeTop )
|
||||
Aig_ObjDelete( p, pObj );
|
||||
if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 )
|
||||
Aig_ObjDelete_rec( p, pFanin0, 1 );
|
||||
if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 )
|
||||
Aig_ObjDelete_rec( p, pFanin1, 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces the first fanin of the node by the new fanin.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew )
|
||||
{
|
||||
Aig_Obj_t * pFaninOld;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_ObjIsPo(pObj) );
|
||||
pFaninOld = Aig_ObjFanin0(pObj);
|
||||
// decrement ref and remove fanout
|
||||
if ( p->pFanData )
|
||||
Aig_ObjRemoveFanout( p, pFaninOld, pObj );
|
||||
Aig_ObjDeref( pFaninOld );
|
||||
// update the fanin
|
||||
pObj->pFanin0 = pFaninNew;
|
||||
// increment ref and add fanout
|
||||
if ( p->pFanData )
|
||||
Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
|
||||
Aig_ObjRef( Aig_ObjFanin0(pObj) );
|
||||
// get rid of old fanin
|
||||
if ( !Aig_ObjIsPi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 )
|
||||
Aig_ObjDelete_rec( p, pFaninOld, 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces node with a buffer fanin by a node without them.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fNodesOnly, int fUpdateLevel )
|
||||
{
|
||||
Aig_Obj_t * pFanReal0, * pFanReal1, * pResult;
|
||||
p->nBufFixes++;
|
||||
if ( Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) );
|
||||
pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) );
|
||||
Aig_ObjPatchFanin0( p, pObj, pFanReal0 );
|
||||
return;
|
||||
}
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) );
|
||||
// get the real fanins
|
||||
pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
|
||||
// get the new node
|
||||
if ( Aig_ObjIsNode(pObj) )
|
||||
pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) );
|
||||
// else if ( Aig_ObjIsLatch(pObj) )
|
||||
// pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) );
|
||||
else
|
||||
assert( 0 );
|
||||
// replace the node with buffer by the node without buffer
|
||||
Aig_ObjReplace( p, pObj, pResult, fNodesOnly, fUpdateLevel );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of dangling nodes removed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManPropagateBuffers( Aig_Man_t * p, int fNodesOnly, int fUpdateLevel )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int nSteps;
|
||||
assert( p->pFanData );
|
||||
for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ )
|
||||
{
|
||||
// get the node with a buffer fanin
|
||||
for ( pObj = Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) );
|
||||
// replace this node by a node without buffer
|
||||
Aig_NodeFixBufferFanins( p, pObj, fNodesOnly, fUpdateLevel );
|
||||
// stop if a cycle occured
|
||||
if ( nSteps > 1000000 )
|
||||
{
|
||||
printf( "Error: A cycle is encountered while propagating buffers.\n" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nSteps;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces one object by another.]
|
||||
|
||||
Description [The new object (pObjNew) should be used instead of the old
|
||||
object (pObjOld). If the new object is complemented or used, the buffer
|
||||
is added and the new object remains in the manager; otherwise, the new
|
||||
object is deleted.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel )
|
||||
{
|
||||
Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew);
|
||||
// the object to be replaced cannot be complemented
|
||||
assert( !Aig_IsComplement(pObjOld) );
|
||||
// the object to be replaced cannot be a terminal
|
||||
assert( !Aig_ObjIsPi(pObjOld) && !Aig_ObjIsPo(pObjOld) );
|
||||
// the object to be used cannot be a buffer or a PO
|
||||
assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsPo(pObjNewR) );
|
||||
// the object cannot be the same
|
||||
assert( pObjOld != pObjNewR );
|
||||
// make sure object is not pointing to itself
|
||||
assert( pObjOld != Aig_ObjFanin0(pObjNewR) );
|
||||
assert( pObjOld != Aig_ObjFanin1(pObjNewR) );
|
||||
// recursively delete the old node - but leave the object there
|
||||
pObjNewR->nRefs++;
|
||||
Aig_ObjDelete_rec( p, pObjOld, 0 );
|
||||
pObjNewR->nRefs--;
|
||||
// if the new object is complemented or already used, create a buffer
|
||||
p->nObjs[pObjOld->Type]--;
|
||||
if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || (fNodesOnly && !Aig_ObjIsNode(pObjNew)) )
|
||||
{
|
||||
pObjOld->Type = AIG_OBJ_BUF;
|
||||
Aig_ObjConnect( p, pObjOld, pObjNew, NULL );
|
||||
p->nBufReplaces++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Aig_Obj_t * pFanin0 = pObjNew->pFanin0;
|
||||
Aig_Obj_t * pFanin1 = pObjNew->pFanin1;
|
||||
int LevelOld = pObjOld->Level;
|
||||
pObjOld->Type = pObjNew->Type;
|
||||
Aig_ObjDisconnect( p, pObjNew );
|
||||
Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 );
|
||||
// delete the new object
|
||||
Aig_ObjDelete( p, pObjNew );
|
||||
// update levels
|
||||
if ( p->pFanData )
|
||||
{
|
||||
pObjOld->Level = LevelOld;
|
||||
Aig_ManUpdateLevel( p, pObjOld );
|
||||
}
|
||||
if ( fUpdateLevel )
|
||||
{
|
||||
Aig_ObjClearReverseLevel( p, pObjOld );
|
||||
Aig_ManUpdateReverseLevel( p, pObjOld );
|
||||
}
|
||||
}
|
||||
p->nObjs[pObjOld->Type]++;
|
||||
// store buffers if fanout is allocated
|
||||
if ( p->pFanData && Aig_ObjIsBuf(pObjOld) )
|
||||
{
|
||||
Vec_PtrPush( p->vBufs, pObjOld );
|
||||
p->nBufMax = AIG_MAX( p->nBufMax, Vec_PtrSize(p->vBufs) );
|
||||
Aig_ManPropagateBuffers( p, fNodesOnly, fUpdateLevel );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,449 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigOper.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [AIG operations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// procedure to detect an EXOR gate
|
||||
static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 )
|
||||
{
|
||||
if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) )
|
||||
return 0;
|
||||
p0 = Aig_Regular(p0);
|
||||
p1 = Aig_Regular(p1);
|
||||
if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) )
|
||||
return 0;
|
||||
if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) )
|
||||
return 0;
|
||||
if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) )
|
||||
return 0;
|
||||
*ppFan0 = Aig_ObjChild0(p0);
|
||||
*ppFan1 = Aig_ObjChild1(p0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns i-th elementary variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i )
|
||||
{
|
||||
int v;
|
||||
for ( v = Aig_ManPiNum(p); v <= i; v++ )
|
||||
Aig_ObjCreatePi( p );
|
||||
assert( i < Vec_PtrSize(p->vPis) );
|
||||
return Aig_ManPi( p, i );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Perform one operation.]
|
||||
|
||||
Description [The argument nodes can be complemented.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type )
|
||||
{
|
||||
if ( Type == AIG_OBJ_AND )
|
||||
return Aig_And( p, p0, p1 );
|
||||
if ( Type == AIG_OBJ_EXOR )
|
||||
return Aig_Exor( p, p0, p1 );
|
||||
assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates the canonical form of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_CanonPair_rec( Aig_Man_t * p, Aig_Obj_t * pGhost )
|
||||
{
|
||||
Aig_Obj_t * pResult, * pLat0, * pLat1;
|
||||
int fCompl0, fCompl1;
|
||||
Aig_Type_t Type;
|
||||
assert( Aig_ObjIsNode(pGhost) );
|
||||
// consider the case when the pair is canonical
|
||||
if ( !Aig_ObjIsLatch(Aig_ObjFanin0(pGhost)) || !Aig_ObjIsLatch(Aig_ObjFanin1(pGhost)) )
|
||||
{
|
||||
if ( pResult = Aig_TableLookup( p, pGhost ) )
|
||||
return pResult;
|
||||
return Aig_ObjCreate( p, pGhost );
|
||||
}
|
||||
/// remember the latches
|
||||
pLat0 = Aig_ObjFanin0(pGhost);
|
||||
pLat1 = Aig_ObjFanin1(pGhost);
|
||||
// remember type and compls
|
||||
Type = Aig_ObjType(pGhost);
|
||||
fCompl0 = Aig_ObjFaninC0(pGhost);
|
||||
fCompl1 = Aig_ObjFaninC1(pGhost);
|
||||
// call recursively
|
||||
pResult = Aig_Oper( p, Aig_NotCond(Aig_ObjChild0(pLat0), fCompl0), Aig_NotCond(Aig_ObjChild0(pLat1), fCompl1), Type );
|
||||
// build latch on top of this
|
||||
return Aig_Latch( p, pResult, (Type == AIG_OBJ_AND)? fCompl0 & fCompl1 : fCompl0 ^ fCompl1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs canonicization step.]
|
||||
|
||||
Description [The argument nodes can be complemented.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
|
||||
{
|
||||
Aig_Obj_t * pGhost, * pResult;
|
||||
// Aig_Obj_t * pFan0, * pFan1;
|
||||
// check trivial cases
|
||||
if ( p0 == p1 )
|
||||
return p0;
|
||||
if ( p0 == Aig_Not(p1) )
|
||||
return Aig_Not(p->pConst1);
|
||||
if ( Aig_Regular(p0) == p->pConst1 )
|
||||
return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1);
|
||||
if ( Aig_Regular(p1) == p->pConst1 )
|
||||
return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1);
|
||||
// check if it can be an EXOR gate
|
||||
// if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
|
||||
// return Aig_Exor( p, pFan0, pFan1 );
|
||||
pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND );
|
||||
pResult = Aig_CanonPair_rec( p, pGhost );
|
||||
return pResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates the canonical form of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne )
|
||||
{
|
||||
Aig_Obj_t * pGhost, * pResult;
|
||||
pGhost = Aig_ObjCreateGhost( p, Aig_NotCond(pObj, fInitOne), NULL, AIG_OBJ_LATCH );
|
||||
pResult = Aig_TableLookup( p, pGhost );
|
||||
if ( pResult == NULL )
|
||||
pResult = Aig_ObjCreate( p, pGhost );
|
||||
return Aig_NotCond( pResult, fInitOne );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs canonicization step.]
|
||||
|
||||
Description [The argument nodes can be complemented.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
|
||||
{
|
||||
/*
|
||||
Aig_Obj_t * pGhost, * pResult;
|
||||
// check trivial cases
|
||||
if ( p0 == p1 )
|
||||
return Aig_Not(p->pConst1);
|
||||
if ( p0 == Aig_Not(p1) )
|
||||
return p->pConst1;
|
||||
if ( Aig_Regular(p0) == p->pConst1 )
|
||||
return Aig_NotCond( p1, p0 == p->pConst1 );
|
||||
if ( Aig_Regular(p1) == p->pConst1 )
|
||||
return Aig_NotCond( p0, p1 == p->pConst1 );
|
||||
// check the table
|
||||
pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR );
|
||||
if ( pResult = Aig_TableLookup( p, pGhost ) )
|
||||
return pResult;
|
||||
return Aig_ObjCreate( p, pGhost );
|
||||
*/
|
||||
return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements Boolean OR.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
|
||||
{
|
||||
return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements ITE operation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 )
|
||||
{
|
||||
/*
|
||||
Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp;
|
||||
int Count0, Count1;
|
||||
// consider trivial cases
|
||||
if ( p0 == Aig_Not(p1) )
|
||||
return Aig_Exor( p, pC, p0 );
|
||||
// other cases can be added
|
||||
// implement the first MUX (F = C * x1 + C' * x0)
|
||||
|
||||
// check for constants here!!!
|
||||
|
||||
pTempA1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, p1, AIG_OBJ_AND) );
|
||||
pTempA2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), p0, AIG_OBJ_AND) );
|
||||
if ( pTempA1 && pTempA2 )
|
||||
{
|
||||
pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempA1), Aig_Not(pTempA2), AIG_OBJ_AND) );
|
||||
if ( pTemp ) return Aig_Not(pTemp);
|
||||
}
|
||||
Count0 = (pTempA1 != NULL) + (pTempA2 != NULL);
|
||||
// implement the second MUX (F' = C * x1' + C' * x0')
|
||||
pTempB1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, Aig_Not(p1), AIG_OBJ_AND) );
|
||||
pTempB2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), Aig_Not(p0), AIG_OBJ_AND) );
|
||||
if ( pTempB1 && pTempB2 )
|
||||
{
|
||||
pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempB1), Aig_Not(pTempB2), AIG_OBJ_AND) );
|
||||
if ( pTemp ) return pTemp;
|
||||
}
|
||||
Count1 = (pTempB1 != NULL) + (pTempB2 != NULL);
|
||||
// compare and decide which one to implement
|
||||
if ( Count0 >= Count1 )
|
||||
{
|
||||
pTempA1 = pTempA1? pTempA1 : Aig_And(p, pC, p1);
|
||||
pTempA2 = pTempA2? pTempA2 : Aig_And(p, Aig_Not(pC), p0);
|
||||
return Aig_Or( p, pTempA1, pTempA2 );
|
||||
}
|
||||
pTempB1 = pTempB1? pTempB1 : Aig_And(p, pC, Aig_Not(p1));
|
||||
pTempB2 = pTempB2? pTempB2 : Aig_And(p, Aig_Not(pC), Aig_Not(p0));
|
||||
return Aig_Not( Aig_Or( p, pTempB1, pTempB2 ) );
|
||||
*/
|
||||
return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements ITE operation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC )
|
||||
{
|
||||
return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Constructs the well-balanced tree of gates.]
|
||||
|
||||
Description [Disregards levels and possible logic sharing.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type )
|
||||
{
|
||||
Aig_Obj_t * pObj1, * pObj2;
|
||||
if ( nObjs == 1 )
|
||||
return ppObjs[0];
|
||||
pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type );
|
||||
pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type );
|
||||
return Aig_Oper( p, pObj1, pObj2, Type );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Old code.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type )
|
||||
{
|
||||
assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR );
|
||||
assert( nArgs > 0 );
|
||||
return Aig_Multi_rec( p, pArgs, nArgs, Type );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements the miter.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs )
|
||||
{
|
||||
int i;
|
||||
assert( vPairs->nSize > 0 );
|
||||
assert( vPairs->nSize % 2 == 0 );
|
||||
for ( i = 0; i < vPairs->nSize; i += 2 )
|
||||
vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) );
|
||||
vPairs->nSize = vPairs->nSize/2;
|
||||
return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements the miter.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 )
|
||||
{
|
||||
int i;
|
||||
assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 );
|
||||
assert( vNodes1->nSize == vNodes2->nSize );
|
||||
for ( i = 0; i < vNodes1->nSize; i++ )
|
||||
vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, vNodes1->pArray[i], vNodes2->pArray[i] ) );
|
||||
return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates AND function with nVars inputs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars )
|
||||
{
|
||||
Aig_Obj_t * pFunc;
|
||||
int i;
|
||||
pFunc = Aig_ManConst1( p );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) );
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates AND function with nVars inputs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars )
|
||||
{
|
||||
Aig_Obj_t * pFunc;
|
||||
int i;
|
||||
pFunc = Aig_ManConst0( p );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) );
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates AND function with nVars inputs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars )
|
||||
{
|
||||
Aig_Obj_t * pFunc;
|
||||
int i;
|
||||
pFunc = Aig_ManConst0( p );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) );
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigOrder.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Dynamically updated topological order.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Initializes the order datastructure.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManOrderStart( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( Aig_ManBufNum(p) == 0 );
|
||||
// allocate order datastructure
|
||||
assert( p->pOrderData == NULL );
|
||||
p->nOrderAlloc = 2 * Aig_ManObjIdMax(p);
|
||||
if ( p->nOrderAlloc < (1<<12) )
|
||||
p->nOrderAlloc = (1<<12);
|
||||
p->pOrderData = ALLOC( unsigned, 2 * p->nOrderAlloc );
|
||||
memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc );
|
||||
// add the constant node
|
||||
p->pOrderData[0] = p->pOrderData[1] = 0;
|
||||
p->iPrev = p->iNext = 0;
|
||||
// add the internal nodes
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
Aig_ObjOrderInsert( p, pObj->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deletes the order datastructure.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManOrderStop( Aig_Man_t * p )
|
||||
{
|
||||
assert( p->pOrderData );
|
||||
FREE( p->pOrderData );
|
||||
p->nOrderAlloc = 0;
|
||||
p->iPrev = p->iNext = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Inserts an entry before iNext.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId )
|
||||
{
|
||||
int iPrev;
|
||||
assert( ObjId != 0 );
|
||||
assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) );
|
||||
if ( ObjId >= p->nOrderAlloc )
|
||||
{
|
||||
int nOrderAlloc = 2 * ObjId;
|
||||
p->pOrderData = REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc );
|
||||
memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) );
|
||||
p->nOrderAlloc = nOrderAlloc;
|
||||
}
|
||||
assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF ); // prev
|
||||
assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next
|
||||
iPrev = p->pOrderData[2*p->iNext];
|
||||
assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext );
|
||||
p->pOrderData[2*ObjId] = iPrev;
|
||||
p->pOrderData[2*iPrev+1] = ObjId;
|
||||
p->pOrderData[2*p->iNext] = ObjId;
|
||||
p->pOrderData[2*ObjId+1] = p->iNext;
|
||||
p->nAndTotal++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Removes the entry.]
|
||||
|
||||
Description [If iPrev is removed, it slides backward.
|
||||
If iNext is removed, it slides forward.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId )
|
||||
{
|
||||
int iPrev, iNext;
|
||||
assert( ObjId != 0 );
|
||||
assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) );
|
||||
iPrev = p->pOrderData[2*ObjId];
|
||||
iNext = p->pOrderData[2*ObjId+1];
|
||||
p->pOrderData[2*ObjId] = 0xFFFFFFFF;
|
||||
p->pOrderData[2*ObjId+1] = 0xFFFFFFFF;
|
||||
p->pOrderData[2*iNext] = iPrev;
|
||||
p->pOrderData[2*iPrev+1] = iNext;
|
||||
if ( p->iPrev == ObjId )
|
||||
{
|
||||
p->nAndPrev--;
|
||||
p->iPrev = iPrev;
|
||||
}
|
||||
if ( p->iNext == ObjId )
|
||||
p->iNext = iNext;
|
||||
p->nAndTotal--;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Advances the order forward.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjOrderAdvance( Aig_Man_t * p )
|
||||
{
|
||||
assert( p->pOrderData );
|
||||
assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext );
|
||||
p->iPrev = p->iNext;
|
||||
p->nAndPrev++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,928 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigPart.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [AIG partitioning package.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Part_Man_t_ Part_Man_t;
|
||||
struct Part_Man_t_
|
||||
{
|
||||
int nChunkSize; // the size of one chunk of memory (~1 Mb)
|
||||
int nStepSize; // the step size in saving memory (~64 bytes)
|
||||
char * pFreeBuf; // the pointer to free memory
|
||||
int nFreeSize; // the size of remaining free memory
|
||||
Vec_Ptr_t * vMemory; // the memory allocated
|
||||
Vec_Ptr_t * vFree; // the vector of free pieces of memory
|
||||
};
|
||||
|
||||
typedef struct Part_One_t_ Part_One_t;
|
||||
struct Part_One_t_
|
||||
{
|
||||
int nRefs; // the number of references
|
||||
int nOuts; // the number of outputs
|
||||
int nOutsAlloc; // the array size
|
||||
int pOuts[0]; // the array of outputs
|
||||
};
|
||||
|
||||
static inline int Part_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); }
|
||||
static inline char * Part_OneNext( char * pPart ) { return *((char **)pPart); }
|
||||
static inline void Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Start the memory manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize )
|
||||
{
|
||||
Part_Man_t * p;
|
||||
p = ALLOC( Part_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Part_Man_t) );
|
||||
p->nChunkSize = nChunkSize;
|
||||
p->nStepSize = nStepSize;
|
||||
p->vMemory = Vec_PtrAlloc( 1000 );
|
||||
p->vFree = Vec_PtrAlloc( 1000 );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the memory manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Part_ManStop( Part_Man_t * p )
|
||||
{
|
||||
void * pMemory;
|
||||
int i;
|
||||
Vec_PtrForEachEntry( p->vMemory, pMemory, i )
|
||||
free( pMemory );
|
||||
Vec_PtrFree( p->vMemory );
|
||||
Vec_PtrFree( p->vFree );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Fetches the memory entry of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Part_ManFetch( Part_Man_t * p, int nSize )
|
||||
{
|
||||
int Type, nSizeReal;
|
||||
char * pMemory;
|
||||
assert( nSize > 0 );
|
||||
Type = Part_SizeType( nSize, p->nStepSize );
|
||||
Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
|
||||
if ( pMemory = Vec_PtrEntry( p->vFree, Type ) )
|
||||
{
|
||||
Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) );
|
||||
return pMemory;
|
||||
}
|
||||
nSizeReal = p->nStepSize * Type;
|
||||
if ( p->nFreeSize < nSizeReal )
|
||||
{
|
||||
p->pFreeBuf = ALLOC( char, p->nChunkSize );
|
||||
p->nFreeSize = p->nChunkSize;
|
||||
Vec_PtrPush( p->vMemory, p->pFreeBuf );
|
||||
}
|
||||
assert( p->nFreeSize >= nSizeReal );
|
||||
pMemory = p->pFreeBuf;
|
||||
p->pFreeBuf += nSizeReal;
|
||||
p->nFreeSize -= nSizeReal;
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recycles the memory entry of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize )
|
||||
{
|
||||
int Type;
|
||||
Type = Part_SizeType( nSize, p->nStepSize );
|
||||
Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
|
||||
Part_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) );
|
||||
Vec_PtrWriteEntry( p->vFree, Type, pMemory );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Fetches the memory entry of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs )
|
||||
{
|
||||
Part_One_t * pPart;
|
||||
pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords );
|
||||
pPart->nRefs = nRefs;
|
||||
pPart->nOuts = 0;
|
||||
pPart->nOutsAlloc = nWords;
|
||||
return pPart;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recycles the memory entry of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry )
|
||||
{
|
||||
assert( pEntry->nOuts <= pEntry->nOutsAlloc );
|
||||
assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 );
|
||||
Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two entries.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs )
|
||||
{
|
||||
Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs );
|
||||
int * pBeg1 = p1->pOuts;
|
||||
int * pBeg2 = p2->pOuts;
|
||||
int * pBeg = p->pOuts;
|
||||
int * pEnd1 = p1->pOuts + p1->nOuts;
|
||||
int * pEnd2 = p2->pOuts + p2->nOuts;
|
||||
while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
|
||||
{
|
||||
if ( *pBeg1 == *pBeg2 )
|
||||
*pBeg++ = *pBeg1++, pBeg2++;
|
||||
else if ( *pBeg1 < *pBeg2 )
|
||||
*pBeg++ = *pBeg1++;
|
||||
else
|
||||
*pBeg++ = *pBeg2++;
|
||||
}
|
||||
while ( pBeg1 < pEnd1 )
|
||||
*pBeg++ = *pBeg1++;
|
||||
while ( pBeg2 < pEnd2 )
|
||||
*pBeg++ = *pBeg2++;
|
||||
p->nOuts = pBeg - p->pOuts;
|
||||
assert( p->nOuts <= p->nOutsAlloc );
|
||||
assert( p->nOuts >= p1->nOuts );
|
||||
assert( p->nOuts >= p2->nOuts );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Tranfers the entry.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Part_ManTransferEntry( Part_One_t * p )
|
||||
{
|
||||
Vec_Int_t * vSupp;
|
||||
int i;
|
||||
vSupp = Vec_IntAlloc( p->nOuts );
|
||||
for ( i = 0; i < p->nOuts; i++ )
|
||||
Vec_IntPush( vSupp, p->pOuts[i] );
|
||||
return vSupp;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes supports of the POs in the multi-output AIG.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Vec_t * Aig_ManSupports( Aig_Man_t * pMan )
|
||||
{
|
||||
Vec_Vec_t * vSupps;
|
||||
Vec_Int_t * vSupp;
|
||||
Part_Man_t * p;
|
||||
Part_One_t * pPart0, * pPart1;
|
||||
Aig_Obj_t * pObj;
|
||||
int i, iIns = 0, iOut = 0;
|
||||
// start the support computation manager
|
||||
p = Part_ManStart( 1 << 20, 1 << 6 );
|
||||
// consider objects in the topological order
|
||||
vSupps = Vec_VecAlloc( Aig_ManPoNum(pMan) );
|
||||
Aig_ManCleanData(pMan);
|
||||
Aig_ManForEachObj( pMan, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjIsNode(pObj) )
|
||||
{
|
||||
pPart0 = Aig_ObjFanin0(pObj)->pData;
|
||||
pPart1 = Aig_ObjFanin1(pObj)->pData;
|
||||
pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs );
|
||||
assert( pPart0->nRefs > 0 );
|
||||
if ( --pPart0->nRefs == 0 )
|
||||
Part_ManRecycleEntry( p, pPart0 );
|
||||
assert( pPart1->nRefs > 0 );
|
||||
if ( --pPart1->nRefs == 0 )
|
||||
Part_ManRecycleEntry( p, pPart1 );
|
||||
continue;
|
||||
}
|
||||
if ( Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
pPart0 = Aig_ObjFanin0(pObj)->pData;
|
||||
vSupp = Part_ManTransferEntry(pPart0);
|
||||
Vec_IntPush( vSupp, iOut++ );
|
||||
Vec_PtrPush( (Vec_Ptr_t *)vSupps, vSupp );
|
||||
assert( pPart0->nRefs > 0 );
|
||||
if ( --pPart0->nRefs == 0 )
|
||||
Part_ManRecycleEntry( p, pPart0 );
|
||||
continue;
|
||||
}
|
||||
if ( Aig_ObjIsPi(pObj) )
|
||||
{
|
||||
if ( pObj->nRefs )
|
||||
{
|
||||
pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs );
|
||||
pPart0->pOuts[ pPart0->nOuts++ ] = iIns++;
|
||||
pObj->pData = pPart0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( Aig_ObjIsConst1(pObj) )
|
||||
{
|
||||
if ( pObj->nRefs )
|
||||
pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs );
|
||||
continue;
|
||||
}
|
||||
assert( 0 );
|
||||
}
|
||||
printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) );
|
||||
Part_ManStop( p );
|
||||
// sort supports by size
|
||||
Vec_VecSort( vSupps, 1 );
|
||||
/*
|
||||
Aig_ManForEachPo( pMan, pObj, i )
|
||||
printf( "%d ", Vec_IntSize( (Vec_Int_t *)Vec_VecEntry(vSupps, i) ) );
|
||||
printf( "\n" );
|
||||
*/
|
||||
return vSupps;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Start char-bases support representation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis )
|
||||
{
|
||||
char * pBuffer;
|
||||
int i, Entry;
|
||||
pBuffer = ALLOC( char, nPis );
|
||||
memset( pBuffer, 0, sizeof(char) * nPis );
|
||||
Vec_IntForEachEntry( vOne, Entry, i )
|
||||
{
|
||||
assert( Entry < nPis );
|
||||
pBuffer[Entry] = 1;
|
||||
}
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Add to char-bases support representation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManSuppCharAdd( char * pBuffer, Vec_Int_t * vOne, int nPis )
|
||||
{
|
||||
int i, Entry;
|
||||
Vec_IntForEachEntry( vOne, Entry, i )
|
||||
{
|
||||
assert( Entry < nPis );
|
||||
pBuffer[Entry] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find the common variables using char-bases support representation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManSuppCharCommon( char * pBuffer, Vec_Int_t * vOne )
|
||||
{
|
||||
int i, Entry, nCommon = 0;
|
||||
Vec_IntForEachEntry( vOne, Entry, i )
|
||||
nCommon += pBuffer[Entry];
|
||||
return nCommon;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find the best partition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nPartSizeLimit, Vec_Int_t * vOne )
|
||||
{
|
||||
Vec_Int_t * vPartSupp, * vPart;
|
||||
int Attract, Repulse, Value, ValueBest;
|
||||
int i, nCommon, iBest;
|
||||
iBest = -1;
|
||||
ValueBest = 0;
|
||||
Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i )
|
||||
{
|
||||
vPart = Vec_PtrEntry( vPartsAll, i );
|
||||
if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit )
|
||||
continue;
|
||||
// nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne );
|
||||
nCommon = Aig_ManSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne );
|
||||
if ( nCommon == 0 )
|
||||
continue;
|
||||
if ( nCommon == Vec_IntSize(vOne) )
|
||||
return i;
|
||||
Attract = 1000 * nCommon / Vec_IntSize(vOne);
|
||||
if ( Vec_IntSize(vPartSupp) < 100 )
|
||||
Repulse = 1;
|
||||
else
|
||||
Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100);
|
||||
Value = Attract/Repulse;
|
||||
if ( ValueBest < Value )
|
||||
{
|
||||
ValueBest = Value;
|
||||
iBest = i;
|
||||
}
|
||||
}
|
||||
if ( ValueBest < 75 )
|
||||
return -1;
|
||||
return iBest;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Perform the smart partitioning.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll )
|
||||
{
|
||||
Vec_Int_t * vOne;
|
||||
int i, nOutputs, Counter;
|
||||
|
||||
Counter = 0;
|
||||
Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
|
||||
{
|
||||
nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i));
|
||||
printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs );
|
||||
Counter += nOutputs;
|
||||
if ( i == Vec_PtrSize(vPartsAll) - 1 )
|
||||
break;
|
||||
}
|
||||
assert( Counter == Aig_ManPoNum(p) );
|
||||
printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManPoNum(p) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Perform the smart partitioning.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nPartSizeLimit )
|
||||
{
|
||||
Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
|
||||
int i, iPart;
|
||||
|
||||
if ( nPartSizeLimit == 0 )
|
||||
nPartSizeLimit = 200;
|
||||
|
||||
// pack smaller partitions into larger blocks
|
||||
iPart = 0;
|
||||
vPart = vPartSupp = NULL;
|
||||
Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
|
||||
{
|
||||
if ( Vec_IntSize(vOne) < nPartSizeLimit )
|
||||
{
|
||||
if ( vPartSupp == NULL )
|
||||
{
|
||||
assert( vPart == NULL );
|
||||
vPartSupp = Vec_IntDup(vOne);
|
||||
vPart = Vec_PtrEntry(vPartsAll, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
|
||||
Vec_IntFree( vTemp );
|
||||
vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) );
|
||||
Vec_IntFree( vTemp );
|
||||
Vec_IntFree( Vec_PtrEntry(vPartsAll, i) );
|
||||
}
|
||||
if ( Vec_IntSize(vPartSupp) < nPartSizeLimit )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
vPart = Vec_PtrEntry(vPartsAll, i);
|
||||
// add the partition
|
||||
Vec_PtrWriteEntry( vPartsAll, iPart, vPart );
|
||||
vPart = NULL;
|
||||
if ( vPartSupp )
|
||||
{
|
||||
Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) );
|
||||
Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
|
||||
vPartSupp = NULL;
|
||||
}
|
||||
iPart++;
|
||||
}
|
||||
// add the last one
|
||||
if ( vPart )
|
||||
{
|
||||
Vec_PtrWriteEntry( vPartsAll, iPart, vPart );
|
||||
vPart = NULL;
|
||||
|
||||
assert( vPartSupp != NULL );
|
||||
Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) );
|
||||
Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
|
||||
vPartSupp = NULL;
|
||||
iPart++;
|
||||
}
|
||||
Vec_PtrShrink( vPartsAll, iPart );
|
||||
Vec_PtrShrink( vPartsAll, iPart );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Perform the smart partitioning.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Vec_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Vec_t ** pvPartSupps )
|
||||
{
|
||||
Vec_Ptr_t * vPartSuppsChar;
|
||||
Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr;
|
||||
Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
|
||||
int i, iPart, iOut, clk;
|
||||
|
||||
// compute the supports for all outputs
|
||||
clk = clock();
|
||||
vSupps = (Vec_Ptr_t *)Aig_ManSupports( p );
|
||||
if ( fVerbose )
|
||||
{
|
||||
PRT( "Supps", clock() - clk );
|
||||
}
|
||||
// start char-based support representation
|
||||
vPartSuppsChar = Vec_PtrAlloc( 1000 );
|
||||
|
||||
// create partitions
|
||||
clk = clock();
|
||||
vPartsAll = Vec_PtrAlloc( 256 );
|
||||
vPartSuppsAll = Vec_PtrAlloc( 256 );
|
||||
Vec_PtrForEachEntry( vSupps, vOne, i )
|
||||
{
|
||||
// get the output number
|
||||
iOut = Vec_IntPop(vOne);
|
||||
// find closely matching part
|
||||
iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nPartSizeLimit, vOne );
|
||||
//printf( "%4d->%4d ", i, iPart );
|
||||
if ( iPart == -1 )
|
||||
{
|
||||
// create new partition
|
||||
vPart = Vec_IntAlloc( 32 );
|
||||
Vec_IntPush( vPart, iOut );
|
||||
// create new partition support
|
||||
vPartSupp = Vec_IntDup( vOne );
|
||||
// add this partition and its support
|
||||
Vec_PtrPush( vPartsAll, vPart );
|
||||
Vec_PtrPush( vPartSuppsAll, vPartSupp );
|
||||
|
||||
Vec_PtrPush( vPartSuppsChar, Aig_ManSuppCharStart(vOne, Aig_ManPiNum(p)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// add output to this partition
|
||||
vPart = Vec_PtrEntry( vPartsAll, iPart );
|
||||
Vec_IntPush( vPart, iOut );
|
||||
// merge supports
|
||||
vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart );
|
||||
vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
|
||||
Vec_IntFree( vTemp );
|
||||
// reinsert new support
|
||||
Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
|
||||
|
||||
Aig_ManSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Aig_ManPiNum(p) );
|
||||
}
|
||||
}
|
||||
|
||||
// stop char-based support representation
|
||||
Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i )
|
||||
free( vTemp );
|
||||
Vec_PtrFree( vPartSuppsChar );
|
||||
|
||||
//printf( "\n" );
|
||||
if ( fVerbose )
|
||||
{
|
||||
PRT( "Parts", clock() - clk );
|
||||
}
|
||||
|
||||
clk = clock();
|
||||
// reorder partitions in the decreasing order of support sizes
|
||||
// remember partition number in each partition support
|
||||
Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
|
||||
Vec_IntPush( vOne, i );
|
||||
// sort the supports in the decreasing order
|
||||
Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 );
|
||||
// reproduce partitions
|
||||
vPartsAll2 = Vec_PtrAlloc( 256 );
|
||||
Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
|
||||
Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) );
|
||||
Vec_PtrFree( vPartsAll );
|
||||
vPartsAll = vPartsAll2;
|
||||
|
||||
// compact small partitions
|
||||
// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
|
||||
Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nPartSizeLimit );
|
||||
if ( fVerbose )
|
||||
// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
|
||||
printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
|
||||
|
||||
if ( fVerbose )
|
||||
{
|
||||
//PRT( "Comps", clock() - clk );
|
||||
}
|
||||
|
||||
// cleanup
|
||||
Vec_VecFree( (Vec_Vec_t *)vSupps );
|
||||
if ( pvPartSupps == NULL )
|
||||
Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
|
||||
else
|
||||
*pvPartSupps = (Vec_Vec_t *)vPartSuppsAll;
|
||||
/*
|
||||
// converts from intergers to nodes
|
||||
Vec_PtrForEachEntry( vPartsAll, vPart, iPart )
|
||||
{
|
||||
vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) );
|
||||
Vec_IntForEachEntry( vPart, iOut, i )
|
||||
Vec_PtrPush( vPartPtr, Aig_ManPo(p, iOut) );
|
||||
Vec_IntFree( vPart );
|
||||
Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
|
||||
}
|
||||
*/
|
||||
return (Vec_Vec_t *)vPartsAll;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Perform the naive partitioning.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Vec_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize )
|
||||
{
|
||||
Vec_Vec_t * vParts;
|
||||
Aig_Obj_t * pObj;
|
||||
int nParts, i;
|
||||
nParts = (Aig_ManPoNum(p) / nPartSize) + ((Aig_ManPoNum(p) % nPartSize) > 0);
|
||||
vParts = Vec_VecStart( nParts );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Vec_VecPush( vParts, i / nPartSize, pObj );
|
||||
return vParts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds internal nodes in the topological order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return pObj->pData;
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
Aig_ManDupPart_rec( pNew, p, Aig_ObjFanin0(pObj) );
|
||||
Aig_ManDupPart_rec( pNew, p, Aig_ObjFanin1(pObj) );
|
||||
pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
||||
assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
return pObj->pData;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds internal nodes in the topological order.]
|
||||
|
||||
Description [Returns the array of new outputs.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * p, Vec_Int_t * vPart, Vec_Int_t * vPartSupp, int fInverse )
|
||||
{
|
||||
Vec_Ptr_t * vOutputs;
|
||||
Aig_Obj_t * pObj, * pObjNew;
|
||||
int Entry, k;
|
||||
// create the PIs
|
||||
Aig_ManIncrementTravId( p );
|
||||
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
if ( !fInverse )
|
||||
{
|
||||
Vec_IntForEachEntry( vPartSupp, Entry, k )
|
||||
{
|
||||
pObj = Aig_ManPi( p, Entry );
|
||||
pObj->pData = Aig_ManPi( pNew, k );
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec_IntForEachEntry( vPartSupp, Entry, k )
|
||||
{
|
||||
pObj = Aig_ManPi( p, k );
|
||||
pObj->pData = Aig_ManPi( pNew, Entry );
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
}
|
||||
}
|
||||
// create the internal nodes
|
||||
vOutputs = Vec_PtrAlloc( Vec_IntSize(vPart) );
|
||||
Vec_IntForEachEntry( vPart, Entry, k )
|
||||
{
|
||||
pObj = Aig_ManPo( p, Entry );
|
||||
pObjNew = Aig_ManDupPart_rec( pNew, p, Aig_ObjFanin0(pObj) );
|
||||
pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
|
||||
Vec_PtrPush( vOutputs, pObjNew );
|
||||
}
|
||||
return vOutputs;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create partitioned miter of the two AIGs.]
|
||||
|
||||
Description [Assumes that each output in the second AIG cannot have
|
||||
more supp vars than the same output in the first AIG.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pMiter;
|
||||
Vec_Ptr_t * vMiters, * vNodes1, * vNodes2;
|
||||
Vec_Vec_t * vParts, * vPartSupps;
|
||||
Vec_Int_t * vPart, * vPartSupp;
|
||||
int i, k;
|
||||
// partition the first manager
|
||||
vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps );
|
||||
// derive miters
|
||||
vMiters = Vec_PtrAlloc( Vec_VecSize(vParts) );
|
||||
for ( i = 0; i < Vec_VecSize(vParts); i++ )
|
||||
{
|
||||
// get partitions and their support
|
||||
vPart = Vec_PtrEntry( (Vec_Ptr_t *)vParts, i );
|
||||
vPartSupp = Vec_PtrEntry( (Vec_Ptr_t *)vPartSupps, i );
|
||||
// create the new miter
|
||||
pNew = Aig_ManStart( 1000 );
|
||||
// create the PIs
|
||||
for ( k = 0; k < Vec_IntSize(vPartSupp); k++ )
|
||||
Aig_ObjCreatePi( pNew );
|
||||
// copy the components
|
||||
vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 );
|
||||
vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 );
|
||||
// create the miter
|
||||
pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 );
|
||||
// create the output
|
||||
Aig_ObjCreatePo( pNew, pMiter );
|
||||
// clean up
|
||||
Aig_ManCleanup( pNew );
|
||||
Vec_PtrPush( vMiters, pNew );
|
||||
}
|
||||
Vec_VecFree( vParts );
|
||||
Vec_VecFree( vPartSupps );
|
||||
return vMiters;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs partitioned choice computation.]
|
||||
|
||||
Description [Assumes that each output in the second AIG cannot have
|
||||
more supp vars than the same output in the first AIG.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize )
|
||||
{
|
||||
Aig_Man_t * pChoice, * pNew, * pAig, * p;
|
||||
Aig_Obj_t * pObj;
|
||||
Vec_Ptr_t * vMiters, * vNodes;
|
||||
Vec_Vec_t * vParts, * vPartSupps;
|
||||
Vec_Int_t * vPart, * vPartSupp;
|
||||
int i, k, m;
|
||||
|
||||
// partition the first AIG
|
||||
assert( Vec_PtrSize(vAigs) > 1 );
|
||||
pAig = Vec_PtrEntry( vAigs, 0 );
|
||||
vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, &vPartSupps );
|
||||
|
||||
// derive the AIG partitions
|
||||
vMiters = Vec_PtrAlloc( Vec_VecSize(vParts) );
|
||||
for ( i = 0; i < Vec_VecSize(vParts); i++ )
|
||||
{
|
||||
// get partitions and their support
|
||||
vPart = Vec_PtrEntry( (Vec_Ptr_t *)vParts, i );
|
||||
vPartSupp = Vec_PtrEntry( (Vec_Ptr_t *)vPartSupps, i );
|
||||
// create the new miter
|
||||
pNew = Aig_ManStart( 1000 );
|
||||
// create the PIs
|
||||
for ( k = 0; k < Vec_IntSize(vPartSupp); k++ )
|
||||
Aig_ObjCreatePi( pNew );
|
||||
// copy the components
|
||||
Vec_PtrForEachEntry( vAigs, p, k )
|
||||
{
|
||||
vNodes = Aig_ManDupPart( pNew, p, vPart, vPartSupp, 0 );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, m )
|
||||
Aig_ObjCreatePo( pNew, pObj );
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
// add to the partitions
|
||||
Vec_PtrPush( vMiters, pNew );
|
||||
}
|
||||
|
||||
// perform choicing for each derived AIG
|
||||
Vec_PtrForEachEntry( vMiters, pNew, i )
|
||||
{
|
||||
extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig );
|
||||
pNew = Fra_FraigChoice( p = pNew );
|
||||
Vec_PtrWriteEntry( vMiters, i, pNew );
|
||||
Aig_ManStop( p );
|
||||
}
|
||||
|
||||
// combine the resulting AIGs
|
||||
pNew = Aig_ManStartFrom( pAig );
|
||||
Vec_PtrForEachEntry( vMiters, p, i )
|
||||
{
|
||||
// get partitions and their support
|
||||
vPart = Vec_PtrEntry( (Vec_Ptr_t *)vParts, i );
|
||||
vPartSupp = Vec_PtrEntry( (Vec_Ptr_t *)vPartSupps, i );
|
||||
// copy the component
|
||||
vNodes = Aig_ManDupPart( pNew, p, vPart, vPartSupp, 1 );
|
||||
assert( Vec_PtrSize(vNodes) == Vec_VecSize(vParts) * Vec_PtrSize(vAigs) );
|
||||
// create choice node
|
||||
for ( k = 0; k < Vec_VecSize(vParts); k++ )
|
||||
{
|
||||
for ( m = 0; m < Vec_PtrSize(vAigs); m++ )
|
||||
{
|
||||
pObj = Aig_ObjChild0( Vec_PtrEntry(vNodes, k * Vec_PtrSize(vAigs) + m) );
|
||||
break;
|
||||
}
|
||||
Aig_ObjCreatePo( pNew, pObj );
|
||||
}
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
Vec_VecFree( vParts );
|
||||
Vec_VecFree( vPartSupps );
|
||||
|
||||
// trasfer representatives
|
||||
Aig_ManReprStart( pNew, Aig_ManObjIdMax(pNew)+1 );
|
||||
Vec_PtrForEachEntry( vMiters, p, i )
|
||||
{
|
||||
Aig_ManTransferRepr( pNew, p );
|
||||
Aig_ManStop( p );
|
||||
}
|
||||
Vec_PtrFree( vMiters );
|
||||
|
||||
// derive the result of choicing
|
||||
pChoice = Aig_ManRehash( pNew );
|
||||
if ( pChoice != pNew )
|
||||
Aig_ManStop( pNew );
|
||||
return pChoice;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigRepr.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Handing node representatives.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the array of representatives.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManReprStart( Aig_Man_t * p, int nIdMax )
|
||||
{
|
||||
assert( Aig_ManBufNum(p) == 0 );
|
||||
assert( p->pReprs == NULL );
|
||||
p->nReprsAlloc = nIdMax;
|
||||
p->pReprs = ALLOC( Aig_Obj_t *, p->nReprsAlloc );
|
||||
memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stop the array of representatives.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManReprStop( Aig_Man_t * p )
|
||||
{
|
||||
assert( p->pReprs != NULL );
|
||||
FREE( p->pReprs );
|
||||
p->nReprsAlloc = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Set the representative.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
|
||||
{
|
||||
assert( p->pReprs != NULL );
|
||||
assert( !Aig_IsComplement(pNode1) );
|
||||
assert( !Aig_IsComplement(pNode2) );
|
||||
assert( pNode1->Id < p->nReprsAlloc );
|
||||
assert( pNode2->Id < p->nReprsAlloc );
|
||||
assert( pNode1->Id < pNode2->Id );
|
||||
p->pReprs[pNode2->Id] = pNode1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Set the representative.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
|
||||
{
|
||||
assert( p->pReprs != NULL );
|
||||
assert( !Aig_IsComplement(pNode1) );
|
||||
assert( !Aig_IsComplement(pNode2) );
|
||||
assert( pNode1->Id < p->nReprsAlloc );
|
||||
assert( pNode2->Id < p->nReprsAlloc );
|
||||
if ( pNode1 == pNode2 )
|
||||
return;
|
||||
if ( pNode1->Id < pNode2->Id )
|
||||
p->pReprs[pNode2->Id] = pNode1;
|
||||
else
|
||||
p->pReprs[pNode1->Id] = pNode2;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find representative.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode )
|
||||
{
|
||||
assert( p->pReprs != NULL );
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( pNode->Id < p->nReprsAlloc );
|
||||
assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id );
|
||||
return p->pReprs[pNode->Id];
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Clears the representative.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode )
|
||||
{
|
||||
assert( p->pReprs != NULL );
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( pNode->Id < p->nReprsAlloc );
|
||||
p->pReprs[pNode->Id] = NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find representative transitively.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Aig_Obj_t * Aig_ObjFindReprTrans( Aig_Man_t * p, Aig_Obj_t * pNode )
|
||||
{
|
||||
Aig_Obj_t * pPrev, * pRepr;
|
||||
for ( pPrev = NULL, pRepr = Aig_ObjFindRepr(p, pNode); pRepr; pPrev = pRepr, pRepr = Aig_ObjFindRepr(p, pRepr) );
|
||||
return pPrev;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns representatives of fanin in approapriate polarity.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pRepr;
|
||||
if ( pRepr = Aig_ObjFindRepr(p, pObj) )
|
||||
return Aig_NotCond( pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
|
||||
return pObj->pData;
|
||||
}
|
||||
static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); }
|
||||
static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); }
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates AIG while substituting representatives.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pRepr;
|
||||
int k;
|
||||
assert( pNew->pReprs != NULL );
|
||||
// go through the nodes which have representatives
|
||||
Aig_ManForEachObj( p, pObj, k )
|
||||
if ( pRepr = Aig_ObjFindRepr(p, pObj) )
|
||||
Aig_ObjSetRepr( pNew, Aig_Regular(pRepr->pData), Aig_Regular(pObj->pData) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates AIG while substituting representatives.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pObj, * pRepr;
|
||||
int i;
|
||||
// start the HOP package
|
||||
pNew = Aig_ManStart( Aig_ManObjIdMax(p) + 1 );
|
||||
pNew->nRegs = p->nRegs;
|
||||
Aig_ManReprStart( pNew, Aig_ManObjIdMax(p)+1 );
|
||||
// map the const and primary inputs
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = Aig_ObjCreatePi(pNew);
|
||||
// map the internal nodes
|
||||
//printf( "\n" );
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
{
|
||||
pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) );
|
||||
if ( pRepr = Aig_ObjFindRepr(p, pObj) ) // member of the class
|
||||
{
|
||||
//printf( "Using node %d for node %d.\n", pRepr->Id, pObj->Id );
|
||||
Aig_ObjSetRepr( pNew, Aig_Regular(pRepr->pData), Aig_Regular(pObj->pData) );
|
||||
}
|
||||
}
|
||||
// transfer the POs
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ObjCreatePo( pNew, Aig_ObjChild0Repr(p, pObj) );
|
||||
// check the new manager
|
||||
if ( !Aig_ManCheck(pNew) )
|
||||
printf( "Aig_ManDupRepr: Check has failed.\n" );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transfer representatives and return the number of critical fanouts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManRemapRepr( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pRepr;
|
||||
int i, nFanouts = 0;
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
{
|
||||
pRepr = Aig_ObjFindReprTrans( p, pObj );
|
||||
if ( pRepr == NULL )
|
||||
continue;
|
||||
assert( pRepr->Id < pObj->Id );
|
||||
Aig_ObjSetRepr( p, pObj, pRepr );
|
||||
nFanouts += (pObj->nRefs > 0);
|
||||
}
|
||||
return nFanouts;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pOld is in the TFI of pNew.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld )
|
||||
{
|
||||
// check the trivial cases
|
||||
if ( pNode == NULL )
|
||||
return 0;
|
||||
// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode
|
||||
// return 0;
|
||||
if ( pNode == pOld )
|
||||
return 1;
|
||||
// skip the visited node
|
||||
if ( Aig_ObjIsTravIdCurrent( p, pNode ) )
|
||||
return 0;
|
||||
Aig_ObjSetTravIdCurrent( p, pNode );
|
||||
// check the children
|
||||
if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) )
|
||||
return 1;
|
||||
if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) )
|
||||
return 1;
|
||||
// check equivalent nodes
|
||||
return Aig_ObjCheckTfi_rec( p, p->pEquivs[pNode->Id], pOld );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pOld is in the TFI of pNew.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld )
|
||||
{
|
||||
assert( !Aig_IsComplement(pNew) );
|
||||
assert( !Aig_IsComplement(pOld) );
|
||||
Aig_ManIncrementTravId( p );
|
||||
return Aig_ObjCheckTfi_rec( p, pNew, pOld );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Iteratively rehashes the AIG.]
|
||||
|
||||
Description [The input AIG is assumed to have representatives assigned.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Aig_ManRehash( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Man_t * pTemp;
|
||||
assert( p->pReprs != NULL );
|
||||
while ( Aig_ManRemapRepr( p ) )
|
||||
{
|
||||
p = Aig_ManDupRepr( pTemp = p );
|
||||
Aig_ManStop( pTemp );
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates choices.]
|
||||
|
||||
Description [The input AIG is assumed to have representatives assigned.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCreateChoices( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pRepr;
|
||||
int i;
|
||||
assert( p->pReprs != NULL );
|
||||
// create equivalent nodes in the manager
|
||||
assert( p->pEquivs == NULL );
|
||||
p->pEquivs = ALLOC( Aig_Obj_t *, Aig_ManObjIdMax(p) + 1 );
|
||||
memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * (Aig_ManObjIdMax(p) + 1) );
|
||||
// make the choice nodes
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
{
|
||||
pRepr = Aig_ObjFindRepr( p, pObj );
|
||||
if ( pRepr == NULL )
|
||||
continue;
|
||||
assert( pObj->nRefs == 0 );
|
||||
// skip constant and PI classes
|
||||
if ( !Aig_ObjIsNode(pRepr) )
|
||||
{
|
||||
Aig_ObjClearRepr( p, pObj );
|
||||
continue;
|
||||
}
|
||||
// skip choices with combinatinal loops
|
||||
if ( Aig_ObjCheckTfi( p, pObj, pRepr ) )
|
||||
{
|
||||
Aig_ObjClearRepr( p, pObj );
|
||||
continue;
|
||||
}
|
||||
//printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id );
|
||||
// add choice to the choice node
|
||||
p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id];
|
||||
p->pEquivs[pRepr->Id] = pObj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,500 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigSeq.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Sequential strashing.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigSeq.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts combinational AIG manager into a sequential one.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManSeqStrashConvert( Aig_Man_t * p, int nLatches, int * pInits )
|
||||
{
|
||||
Aig_Obj_t * pObjLi, * pObjLo, * pLatch;
|
||||
int i;
|
||||
assert( Vec_PtrSize( p->vBufs ) == 0 );
|
||||
// collect the POs to be converted into latches
|
||||
for ( i = 0; i < nLatches; i++ )
|
||||
{
|
||||
// get the corresponding PI/PO pair
|
||||
pObjLi = Aig_ManPo( p, Aig_ManPoNum(p) - nLatches + i );
|
||||
pObjLo = Aig_ManPi( p, Aig_ManPiNum(p) - nLatches + i );
|
||||
// create latch
|
||||
pLatch = Aig_Latch( p, Aig_ObjChild0(pObjLi), pInits? pInits[i] : 0 );
|
||||
// recycle the old PO object
|
||||
Aig_ObjDisconnect( p, pObjLi );
|
||||
Vec_PtrWriteEntry( p->vObjs, pObjLi->Id, NULL );
|
||||
Aig_ManRecycleMemory( p, pObjLi );
|
||||
// convert the corresponding PI to be a buffer and connect it to the latch
|
||||
pObjLo->Type = AIG_OBJ_BUF;
|
||||
Aig_ObjConnect( p, pObjLo, pLatch, NULL );
|
||||
// save the buffer
|
||||
// Vec_PtrPush( p->vBufs, pObjLo );
|
||||
}
|
||||
// shrink the arrays
|
||||
Vec_PtrShrink( p->vPis, Aig_ManPiNum(p) - nLatches );
|
||||
Vec_PtrShrink( p->vPos, Aig_ManPoNum(p) - nLatches );
|
||||
// update the counters of different objects
|
||||
p->nObjs[AIG_OBJ_PI] -= nLatches;
|
||||
p->nObjs[AIG_OBJ_PO] -= nLatches;
|
||||
p->nObjs[AIG_OBJ_BUF] += nLatches;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDfsSeq_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( pObj == NULL )
|
||||
return;
|
||||
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
|
||||
return;
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
|
||||
return;
|
||||
Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
Aig_ManDfsSeq_rec( p, Aig_ObjFanin1(pObj), vNodes );
|
||||
// if ( (Aig_ObjFanin0(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin0(pObj))) &&
|
||||
// (Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin1(pObj))) )
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfsSeq( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManIncrementTravId( p );
|
||||
vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDfsUnreach_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( pObj == NULL )
|
||||
return;
|
||||
if ( Aig_ObjIsTravIdPrevious(p, pObj) || Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
return;
|
||||
Aig_ObjSetTravIdPrevious( p, pObj ); // assume unknown
|
||||
Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
Aig_ManDfsUnreach_rec( p, Aig_ObjFanin1(pObj), vNodes );
|
||||
if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) &&
|
||||
(Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj))) )
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
else
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects internal nodes unreachable from PIs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManDfsUnreach( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj, * pFanin;
|
||||
int i, k;//, RetValue;
|
||||
// collect unreachable nodes
|
||||
Aig_ManIncrementTravId( p );
|
||||
Aig_ManIncrementTravId( p );
|
||||
// mark the constant and PIs
|
||||
Aig_ObjSetTravIdPrevious( p, Aig_ManConst1(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
// curr marks visited nodes reachable from PIs
|
||||
// prev marks visited nodes unreachable or unknown
|
||||
|
||||
// collect the unreachable nodes
|
||||
vNodes = Vec_PtrAlloc( 32 );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes );
|
||||
|
||||
// refine resulting nodes
|
||||
do
|
||||
{
|
||||
k = 0;
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
{
|
||||
assert( Aig_ObjIsTravIdPrevious(p, pObj) );
|
||||
if ( Aig_ObjIsLatch(pObj) || Aig_ObjIsBuf(pObj) )
|
||||
{
|
||||
pFanin = Aig_ObjFanin0(pObj);
|
||||
assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pFanin) )
|
||||
{
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else // AND gate
|
||||
{
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
pFanin = Aig_ObjFanin0(pObj);
|
||||
assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pFanin) )
|
||||
{
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
continue;
|
||||
}
|
||||
pFanin = Aig_ObjFanin1(pObj);
|
||||
assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) );
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pFanin) )
|
||||
{
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// write it back
|
||||
Vec_PtrWriteEntry( vNodes, k++, pObj );
|
||||
}
|
||||
Vec_PtrShrink( vNodes, k );
|
||||
}
|
||||
while ( k < i );
|
||||
|
||||
// if ( Vec_PtrSize(vNodes) > 0 )
|
||||
// printf( "Found %d unreachable.\n", Vec_PtrSize(vNodes) );
|
||||
return vNodes;
|
||||
|
||||
/*
|
||||
// the resulting array contains all unreachable nodes except const 1
|
||||
if ( Vec_PtrSize(vNodes) == 0 )
|
||||
{
|
||||
Vec_PtrFree( vNodes );
|
||||
return 0;
|
||||
}
|
||||
RetValue = Vec_PtrSize(vNodes);
|
||||
|
||||
// mark these nodes
|
||||
Aig_ManIncrementTravId( p );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
Vec_PtrFree( vNodes );
|
||||
return RetValue;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Removes nodes that do not fanout into POs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManRemoveUnmarked( Aig_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i, RetValue;
|
||||
// collect unmarked nodes
|
||||
vNodes = Vec_PtrAlloc( 100 );
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjIsTerm(pObj) )
|
||||
continue;
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
continue;
|
||||
//Aig_ObjPrintVerbose( pObj, 0 );
|
||||
Aig_ObjDisconnect( p, pObj );
|
||||
Vec_PtrPush( vNodes, pObj );
|
||||
}
|
||||
if ( Vec_PtrSize(vNodes) == 0 )
|
||||
{
|
||||
Vec_PtrFree( vNodes );
|
||||
return 0;
|
||||
}
|
||||
// remove the dangling objects
|
||||
RetValue = Vec_PtrSize(vNodes);
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
Aig_ObjDelete( p, pObj );
|
||||
// printf( "Removed %d dangling.\n", Vec_PtrSize(vNodes) );
|
||||
Vec_PtrFree( vNodes );
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Rehashes the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManSeqRehashOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t * vUnreach )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1;
|
||||
int i, RetValue = 0, Counter = 0, Counter2 = 0;
|
||||
|
||||
// mark the unreachable nodes
|
||||
Aig_ManIncrementTravId( p );
|
||||
Vec_PtrForEachEntry( vUnreach, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent(p, pObj);
|
||||
/*
|
||||
// count the number of unreachable object connections
|
||||
// that is the number of unreachable objects connected to main objects
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
continue;
|
||||
|
||||
pFanin0 = Aig_ObjFanin0(pObj);
|
||||
if ( pFanin0 == NULL )
|
||||
continue;
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pFanin0) )
|
||||
pFanin0->fMarkA = 1;
|
||||
|
||||
pFanin1 = Aig_ObjFanin1(pObj);
|
||||
if ( pFanin1 == NULL )
|
||||
continue;
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pFanin1) )
|
||||
pFanin1->fMarkA = 1;
|
||||
}
|
||||
|
||||
// count the objects
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
Counter2 += pObj->fMarkA, pObj->fMarkA = 0;
|
||||
printf( "Connections = %d.\n", Counter2 );
|
||||
*/
|
||||
|
||||
// go through the nodes while skipping unreachable
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
{
|
||||
// skip nodes unreachable from the PIs
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
||||
continue;
|
||||
// process the node
|
||||
if ( Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) )
|
||||
continue;
|
||||
pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
Aig_ObjPatchFanin0( p, pObj, pFanin0 );
|
||||
continue;
|
||||
}
|
||||
if ( Aig_ObjIsLatch(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) )
|
||||
continue;
|
||||
pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pObjNew = Aig_Latch( p, pObjNew, 0 );
|
||||
Aig_ObjReplace( p, pObj, pObjNew, 1, 0 );
|
||||
RetValue = 1;
|
||||
Counter++;
|
||||
continue;
|
||||
}
|
||||
if ( Aig_ObjIsNode(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) )
|
||||
continue;
|
||||
pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
|
||||
pObjNew = Aig_And( p, pFanin0, pFanin1 );
|
||||
Aig_ObjReplace( p, pObj, pObjNew, 1, 0 );
|
||||
RetValue = 1;
|
||||
Counter++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// printf( "Rehashings = %d.\n", Counter++ );
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [If AIG contains buffers, this procedure removes them.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManRemoveBuffers( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1;
|
||||
int i;
|
||||
if ( Aig_ManBufNum(p) == 0 )
|
||||
return;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjIsPo(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) )
|
||||
continue;
|
||||
pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
Aig_ObjPatchFanin0( p, pObj, pFanin0 );
|
||||
}
|
||||
else if ( Aig_ObjIsLatch(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) )
|
||||
continue;
|
||||
pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pObjNew = Aig_Latch( p, pFanin0, 0 );
|
||||
Aig_ObjReplace( p, pObj, pObjNew, 0, 0 );
|
||||
}
|
||||
else if ( Aig_ObjIsAnd(pObj) )
|
||||
{
|
||||
if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) )
|
||||
continue;
|
||||
pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
|
||||
pObjNew = Aig_And( p, pFanin0, pFanin1 );
|
||||
Aig_ObjReplace( p, pObj, pObjNew, 0, 0 );
|
||||
}
|
||||
}
|
||||
assert( Aig_ManBufNum(p) == 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits )
|
||||
{
|
||||
Vec_Ptr_t * vNodes, * vUnreach;
|
||||
// Aig_Obj_t * pObj, * pFanin;
|
||||
// int i;
|
||||
int Iter, RetValue = 1;
|
||||
|
||||
// create latches out of the additional PI/PO pairs
|
||||
Aig_ManSeqStrashConvert( p, nLatches, pInits );
|
||||
|
||||
// iteratively rehash the network
|
||||
for ( Iter = 0; RetValue; Iter++ )
|
||||
{
|
||||
// Aig_ManPrintStats( p );
|
||||
/*
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
assert( pObj->Type > 0 );
|
||||
pFanin = Aig_ObjFanin0(pObj);
|
||||
assert( pFanin == NULL || pFanin->Type > 0 );
|
||||
pFanin = Aig_ObjFanin1(pObj);
|
||||
assert( pFanin == NULL || pFanin->Type > 0 );
|
||||
}
|
||||
*/
|
||||
// mark nodes unreachable from the PIs
|
||||
vUnreach = Aig_ManDfsUnreach( p );
|
||||
if ( Iter == 0 && Vec_PtrSize(vUnreach) > 0 )
|
||||
printf( "Unreachable objects = %d.\n", Vec_PtrSize(vUnreach) );
|
||||
// collect nodes reachable from the POs
|
||||
vNodes = Aig_ManDfsSeq( p );
|
||||
// remove nodes unreachable from the POs
|
||||
if ( Iter == 0 )
|
||||
Aig_ManRemoveUnmarked( p );
|
||||
// continue rehashing as long as there are changes
|
||||
RetValue = Aig_ManSeqRehashOne( p, vNodes, vUnreach );
|
||||
Vec_PtrFree( vNodes );
|
||||
Vec_PtrFree( vUnreach );
|
||||
}
|
||||
|
||||
// perform the final cleanup
|
||||
Aig_ManIncrementTravId( p );
|
||||
vNodes = Aig_ManDfsSeq( p );
|
||||
Aig_ManRemoveUnmarked( p );
|
||||
Vec_PtrFree( vNodes );
|
||||
// remove buffers if they are left
|
||||
// Aig_ManRemoveBuffers( p );
|
||||
|
||||
// clean up
|
||||
if ( !Aig_ManCheck( p ) )
|
||||
{
|
||||
printf( "Aig_ManSeqStrash: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [ivyShow.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [And-Inverter Graph package.]
|
||||
|
||||
Synopsis [Visualization of HAIG.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - May 11, 2006.]
|
||||
|
||||
Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes the graph structure of AIG for DOT.]
|
||||
|
||||
Description [Useful for graph visualization using tools such as GraphViz:
|
||||
http://www.graphviz.org/]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
|
||||
{
|
||||
FILE * pFile;
|
||||
Aig_Obj_t * pNode;//, * pTemp, * pPrev;
|
||||
int LevelMax, Level, i;
|
||||
|
||||
if ( Aig_ManNodeNum(pMan) > 200 )
|
||||
{
|
||||
fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" );
|
||||
return;
|
||||
}
|
||||
if ( (pFile = fopen( pFileName, "w" )) == NULL )
|
||||
{
|
||||
fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
|
||||
// mark the nodes
|
||||
if ( vBold )
|
||||
Vec_PtrForEachEntry( vBold, pNode, i )
|
||||
pNode->fMarkB = 1;
|
||||
|
||||
// compute levels
|
||||
// LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig );
|
||||
LevelMax = 1 + Aig_ManLevels( pMan );
|
||||
Aig_ManForEachPo( pMan, pNode, i )
|
||||
pNode->Level = LevelMax;
|
||||
|
||||
// write the DOT header
|
||||
fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "digraph AIG {\n" );
|
||||
fprintf( pFile, "size = \"7.5,10\";\n" );
|
||||
// fprintf( pFile, "ranksep = 0.5;\n" );
|
||||
// fprintf( pFile, "nodesep = 0.5;\n" );
|
||||
fprintf( pFile, "center = true;\n" );
|
||||
// fprintf( pFile, "orientation = landscape;\n" );
|
||||
// fprintf( pFile, "edge [fontsize = 10];\n" );
|
||||
// fprintf( pFile, "edge [dir = none];\n" );
|
||||
fprintf( pFile, "edge [dir = back];\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// labels on the left of the picture
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " node [shape = plaintext];\n" );
|
||||
fprintf( pFile, " edge [style = invis];\n" );
|
||||
fprintf( pFile, " LevelTitle1 [label=\"\"];\n" );
|
||||
fprintf( pFile, " LevelTitle2 [label=\"\"];\n" );
|
||||
// generate node names with labels
|
||||
for ( Level = LevelMax; Level >= 0; Level-- )
|
||||
{
|
||||
// the visible node name
|
||||
fprintf( pFile, " Level%d", Level );
|
||||
fprintf( pFile, " [label = " );
|
||||
// label name
|
||||
fprintf( pFile, "\"" );
|
||||
fprintf( pFile, "\"" );
|
||||
fprintf( pFile, "];\n" );
|
||||
}
|
||||
|
||||
// genetate the sequence of visible/invisible nodes to mark levels
|
||||
fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" );
|
||||
for ( Level = LevelMax; Level >= 0; Level-- )
|
||||
{
|
||||
// the visible node name
|
||||
fprintf( pFile, " Level%d", Level );
|
||||
// the connector
|
||||
if ( Level != 0 )
|
||||
fprintf( pFile, " ->" );
|
||||
else
|
||||
fprintf( pFile, ";" );
|
||||
}
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// generate title box on top
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " rank = same;\n" );
|
||||
fprintf( pFile, " LevelTitle1;\n" );
|
||||
fprintf( pFile, " title1 [shape=plaintext,\n" );
|
||||
fprintf( pFile, " fontsize=20,\n" );
|
||||
fprintf( pFile, " fontname = \"Times-Roman\",\n" );
|
||||
fprintf( pFile, " label=\"" );
|
||||
fprintf( pFile, "%s", "AIG structure visualized by ABC" );
|
||||
fprintf( pFile, "\\n" );
|
||||
fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" );
|
||||
fprintf( pFile, "Time was %s. ", Extra_TimeStamp() );
|
||||
fprintf( pFile, "\"\n" );
|
||||
fprintf( pFile, " ];\n" );
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// generate statistics box
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " rank = same;\n" );
|
||||
fprintf( pFile, " LevelTitle2;\n" );
|
||||
fprintf( pFile, " title2 [shape=plaintext,\n" );
|
||||
fprintf( pFile, " fontsize=18,\n" );
|
||||
fprintf( pFile, " fontname = \"Times-Roman\",\n" );
|
||||
fprintf( pFile, " label=\"" );
|
||||
fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax );
|
||||
fprintf( pFile, "\\n" );
|
||||
fprintf( pFile, "\"\n" );
|
||||
fprintf( pFile, " ];\n" );
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// generate the COs
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " rank = same;\n" );
|
||||
// the labeling node of this level
|
||||
fprintf( pFile, " Level%d;\n", LevelMax );
|
||||
// generate the CO nodes
|
||||
Aig_ManForEachPo( pMan, pNode, i )
|
||||
{
|
||||
/*
|
||||
if ( fHaig || pNode->pEquiv == NULL )
|
||||
fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id,
|
||||
(Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") );
|
||||
else
|
||||
fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id,
|
||||
(Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""),
|
||||
Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
|
||||
*/
|
||||
fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
|
||||
|
||||
fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"invtriangle") );
|
||||
fprintf( pFile, ", color = coral, fillcolor = coral" );
|
||||
fprintf( pFile, "];\n" );
|
||||
}
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// generate nodes of each rank
|
||||
for ( Level = LevelMax - 1; Level > 0; Level-- )
|
||||
{
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " rank = same;\n" );
|
||||
// the labeling node of this level
|
||||
fprintf( pFile, " Level%d;\n", Level );
|
||||
Aig_ManForEachObj( pMan, pNode, i )
|
||||
{
|
||||
if ( (int)pNode->Level != Level )
|
||||
continue;
|
||||
/*
|
||||
if ( fHaig || pNode->pEquiv == NULL )
|
||||
fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
|
||||
else
|
||||
fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id,
|
||||
Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
|
||||
*/
|
||||
fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
|
||||
|
||||
fprintf( pFile, ", shape = ellipse" );
|
||||
if ( vBold && pNode->fMarkB )
|
||||
fprintf( pFile, ", style = filled" );
|
||||
fprintf( pFile, "];\n" );
|
||||
}
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
|
||||
// generate the CI nodes
|
||||
fprintf( pFile, "{\n" );
|
||||
fprintf( pFile, " rank = same;\n" );
|
||||
// the labeling node of this level
|
||||
fprintf( pFile, " Level%d;\n", 0 );
|
||||
// generate constant node
|
||||
if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 )
|
||||
{
|
||||
pNode = Aig_ManConst1(pMan);
|
||||
// check if the costant node is present
|
||||
fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id );
|
||||
fprintf( pFile, ", shape = ellipse" );
|
||||
fprintf( pFile, ", color = coral, fillcolor = coral" );
|
||||
fprintf( pFile, "];\n" );
|
||||
}
|
||||
// generate the CI nodes
|
||||
Aig_ManForEachPi( pMan, pNode, i )
|
||||
{
|
||||
/*
|
||||
if ( fHaig || pNode->pEquiv == NULL )
|
||||
fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id,
|
||||
(Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") );
|
||||
else
|
||||
fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id,
|
||||
(Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""),
|
||||
Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
|
||||
*/
|
||||
fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
|
||||
|
||||
fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"triangle") );
|
||||
fprintf( pFile, ", color = coral, fillcolor = coral" );
|
||||
fprintf( pFile, "];\n" );
|
||||
}
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// generate invisible edges from the square down
|
||||
fprintf( pFile, "title1 -> title2 [style = invis];\n" );
|
||||
Aig_ManForEachPo( pMan, pNode, i )
|
||||
fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") );
|
||||
|
||||
// generate edges
|
||||
Aig_ManForEachObj( pMan, pNode, i )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsPo(pNode) && !Aig_ObjIsBuf(pNode) )
|
||||
continue;
|
||||
// generate the edge from this node to the next
|
||||
fprintf( pFile, "Node%d%s", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") );
|
||||
fprintf( pFile, " -> " );
|
||||
fprintf( pFile, "Node%d%s", Aig_ObjFaninId0(pNode), (Aig_ObjIsLatch(Aig_ObjFanin0(pNode))? "_out":"") );
|
||||
fprintf( pFile, " [" );
|
||||
fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" );
|
||||
// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
|
||||
// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
|
||||
fprintf( pFile, "]" );
|
||||
fprintf( pFile, ";\n" );
|
||||
if ( !Aig_ObjIsNode(pNode) )
|
||||
continue;
|
||||
// generate the edge from this node to the next
|
||||
fprintf( pFile, "Node%d", pNode->Id );
|
||||
fprintf( pFile, " -> " );
|
||||
fprintf( pFile, "Node%d%s", Aig_ObjFaninId1(pNode), (Aig_ObjIsLatch(Aig_ObjFanin1(pNode))? "_out":"") );
|
||||
fprintf( pFile, " [" );
|
||||
fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" );
|
||||
// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
|
||||
// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
|
||||
fprintf( pFile, "]" );
|
||||
fprintf( pFile, ";\n" );
|
||||
/*
|
||||
// generate the edges between the equivalent nodes
|
||||
if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 )
|
||||
{
|
||||
pPrev = pNode;
|
||||
for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) )
|
||||
{
|
||||
fprintf( pFile, "Node%d", pPrev->Id );
|
||||
fprintf( pFile, " -> " );
|
||||
fprintf( pFile, "Node%d", pTemp->Id );
|
||||
fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
|
||||
fprintf( pFile, ";\n" );
|
||||
pPrev = pTemp;
|
||||
}
|
||||
// connect the last node with the first
|
||||
fprintf( pFile, "Node%d", pPrev->Id );
|
||||
fprintf( pFile, " -> " );
|
||||
fprintf( pFile, "Node%d", pNode->Id );
|
||||
fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
|
||||
fprintf( pFile, ";\n" );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fprintf( pFile, "}" );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, "\n" );
|
||||
fclose( pFile );
|
||||
|
||||
// unmark nodes
|
||||
if ( vBold )
|
||||
Vec_PtrForEachEntry( vBold, pNode, i )
|
||||
pNode->fMarkB = 0;
|
||||
|
||||
Aig_ManForEachPo( pMan, pNode, i )
|
||||
pNode->Level = Aig_ObjFanin0(pNode)->Level;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
|
||||
{
|
||||
extern void Abc_ShowFile( char * FileNameDot );
|
||||
static Counter = 0;
|
||||
char FileNameDot[200];
|
||||
FILE * pFile;
|
||||
// create the file name
|
||||
// Aig_ShowGetFileName( pMan->pName, FileNameDot );
|
||||
sprintf( FileNameDot, "temp%02d.dot", Counter++ );
|
||||
// check that the file can be opened
|
||||
if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
|
||||
{
|
||||
fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
|
||||
return;
|
||||
}
|
||||
fclose( pFile );
|
||||
// generate the file
|
||||
Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold );
|
||||
// visualize the file
|
||||
Abc_ShowFile( FileNameDot );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigTable.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Structural hashing table.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// hashing the node
|
||||
static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize )
|
||||
{
|
||||
unsigned long Key = Aig_ObjIsExor(pObj) * 1699;
|
||||
Key ^= Aig_ObjFanin0(pObj)->Id * 7937;
|
||||
Key ^= Aig_ObjFanin1(pObj)->Id * 2971;
|
||||
Key ^= Aig_ObjFaninC0(pObj) * 911;
|
||||
Key ^= Aig_ObjFaninC1(pObj) * 353;
|
||||
return Key % TableSize;
|
||||
}
|
||||
|
||||
// returns the place where this node is stored (or should be stored)
|
||||
static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t ** ppEntry;
|
||||
if ( Aig_ObjIsLatch(pObj) )
|
||||
{
|
||||
assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) == NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) );
|
||||
assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id );
|
||||
}
|
||||
for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
|
||||
if ( *ppEntry == pObj )
|
||||
return ppEntry;
|
||||
assert( *ppEntry == NULL );
|
||||
return ppEntry;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Resizes the table.]
|
||||
|
||||
Description [Typically this procedure should not be called.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_TableResize( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pEntry, * pNext;
|
||||
Aig_Obj_t ** pTableOld, ** ppPlace;
|
||||
int nTableSizeOld, Counter, nEntries, i, clk;
|
||||
clk = clock();
|
||||
// save the old table
|
||||
pTableOld = p->pTable;
|
||||
nTableSizeOld = p->nTableSize;
|
||||
// get the new table
|
||||
p->nTableSize = Aig_PrimeCudd( 2 * Aig_ManNodeNum(p) );
|
||||
p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize );
|
||||
memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
|
||||
// rehash the entries from the old table
|
||||
Counter = 0;
|
||||
for ( i = 0; i < nTableSizeOld; i++ )
|
||||
for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL;
|
||||
pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL )
|
||||
{
|
||||
// get the place where this entry goes in the table
|
||||
ppPlace = Aig_TableFind( p, pEntry );
|
||||
assert( *ppPlace == NULL ); // should not be there
|
||||
// add the entry to the list
|
||||
*ppPlace = pEntry;
|
||||
pEntry->pNext = NULL;
|
||||
Counter++;
|
||||
}
|
||||
nEntries = Aig_ManNodeNum(p);
|
||||
assert( Counter == nEntries );
|
||||
printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize );
|
||||
PRT( "Time", clock() - clk );
|
||||
// replace the table and the parameters
|
||||
free( pTableOld );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if node with the given attributes is in the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost )
|
||||
{
|
||||
Aig_Obj_t * pEntry;
|
||||
assert( !Aig_IsComplement(pGhost) );
|
||||
if ( pGhost->Type == AIG_OBJ_LATCH )
|
||||
{
|
||||
assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) == NULL );
|
||||
if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) )
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( pGhost->Type == AIG_OBJ_AND );
|
||||
assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) );
|
||||
assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id );
|
||||
if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) )
|
||||
return NULL;
|
||||
}
|
||||
for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext )
|
||||
{
|
||||
if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) &&
|
||||
Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) &&
|
||||
Aig_ObjType(pEntry) == Aig_ObjType(pGhost) )
|
||||
return pEntry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if node with the given attributes is in the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 )
|
||||
{
|
||||
Aig_Obj_t * pGhost;
|
||||
// consider simple cases
|
||||
if ( pFanin0 == pFanin1 )
|
||||
return pFanin0;
|
||||
if ( pFanin0 == Aig_Not(pFanin1) )
|
||||
return Aig_ManConst0(p);
|
||||
if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) )
|
||||
return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p);
|
||||
if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) )
|
||||
return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p);
|
||||
pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND );
|
||||
return Aig_TableLookup( p, pGhost );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds the new node to the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t ** ppPlace;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_TableLookup(p, pObj) == NULL );
|
||||
if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) )
|
||||
Aig_TableResize( p );
|
||||
ppPlace = Aig_TableFind( p, pObj );
|
||||
assert( *ppPlace == NULL );
|
||||
*ppPlace = pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deletes the node from the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t ** ppPlace;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
ppPlace = Aig_TableFind( p, pObj );
|
||||
assert( *ppPlace == pObj ); // node should be in the table
|
||||
// remove the node
|
||||
*ppPlace = pObj->pNext;
|
||||
pObj->pNext = NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Count the number of nodes in the table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_TableCountEntries( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pEntry;
|
||||
int i, Counter = 0;
|
||||
for ( i = 0; i < p->nTableSize; i++ )
|
||||
for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
|
||||
Counter++;
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis [Profiles the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Aig_TableProfile( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pEntry;
|
||||
int i, Counter;
|
||||
for ( i = 0; i < p->nTableSize; i++ )
|
||||
{
|
||||
Counter = 0;
|
||||
for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
|
||||
Counter++;
|
||||
if ( Counter )
|
||||
printf( "%d ", Counter );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigTiming.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Incremental updating of direct/reverse AIG levels.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the reverse level of the node.]
|
||||
|
||||
Description [The reverse level is the level of the node in reverse
|
||||
topological order, starting from the COs.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( p->vLevelR );
|
||||
Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 );
|
||||
return Vec_IntEntry(p->vLevelR, pObj->Id);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the reverse level of the node.]
|
||||
|
||||
Description [The reverse level is the level of the node in reverse
|
||||
topological order, starting from the COs.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR )
|
||||
{
|
||||
assert( p->vLevelR );
|
||||
Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 );
|
||||
Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Resets reverse level of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_ObjSetReverseLevel( p, pObj, 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns required level of the node.]
|
||||
|
||||
Description [Converts the reverse levels of the node into its required
|
||||
level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( p->vLevelR );
|
||||
return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the reverse level of the node using its fanout levels.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pFanout;
|
||||
int i, iFanout, LevelCur, Level = 0;
|
||||
Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
|
||||
{
|
||||
LevelCur = Aig_ObjReverseLevel( p, pFanout );
|
||||
Level = AIG_MAX( Level, LevelCur );
|
||||
}
|
||||
return Level + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares for the computation of required levels.]
|
||||
|
||||
Description [This procedure should be called before the required times
|
||||
are used. It starts internal data structures, which records the level
|
||||
from the COs of the network nodes in reverse topologogical order.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( p->pFanData != NULL );
|
||||
assert( p->vLevelR == NULL );
|
||||
// remember the maximum number of direct levels
|
||||
p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease;
|
||||
// start the reverse levels
|
||||
p->vLevelR = Vec_IntAlloc( 0 );
|
||||
Vec_IntFill( p->vLevelR, 1 + Aig_ManObjIdMax(p), 0 );
|
||||
// compute levels in reverse topological order
|
||||
vNodes = Aig_ManDfsReverse( p );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
{
|
||||
assert( pObj->fMarkA == 0 );
|
||||
Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) );
|
||||
}
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Cleans the data structures used to compute required levels.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManStopReverseLevels( Aig_Man_t * p )
|
||||
{
|
||||
assert( p->vLevelR != NULL );
|
||||
Vec_IntFree( p->vLevelR );
|
||||
p->vLevelR = NULL;
|
||||
p->nLevelMax = 0;
|
||||
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Incrementally updates level of the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew )
|
||||
{
|
||||
Aig_Obj_t * pFanout, * pTemp;
|
||||
int iFanout, LevelOld, Lev, k, m;
|
||||
assert( p->pFanData != NULL );
|
||||
assert( Aig_ObjIsNode(pObjNew) );
|
||||
// allocate level if needed
|
||||
if ( p->vLevels == NULL )
|
||||
p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 );
|
||||
// check if level has changed
|
||||
LevelOld = Aig_ObjLevel(pObjNew);
|
||||
if ( LevelOld == Aig_ObjLevelNew(pObjNew) )
|
||||
return;
|
||||
// start the data structure for level update
|
||||
// we cannot fail to visit a node when using this structure because the
|
||||
// nodes are stored by their _old_ levels, which are assumed to be correct
|
||||
Vec_VecClear( p->vLevels );
|
||||
Vec_VecPush( p->vLevels, LevelOld, pObjNew );
|
||||
pObjNew->fMarkA = 1;
|
||||
// recursively update level
|
||||
Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld )
|
||||
{
|
||||
pTemp->fMarkA = 0;
|
||||
assert( Aig_ObjLevel(pTemp) == Lev );
|
||||
pTemp->Level = Aig_ObjLevelNew(pTemp);
|
||||
// if the level did not change, no need to check the fanout levels
|
||||
if ( Aig_ObjLevel(pTemp) == Lev )
|
||||
continue;
|
||||
// schedule fanout for level update
|
||||
Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m )
|
||||
{
|
||||
if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA )
|
||||
{
|
||||
assert( Aig_ObjLevel(pFanout) >= Lev );
|
||||
Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout );
|
||||
pFanout->fMarkA = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Incrementally updates level of the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew )
|
||||
{
|
||||
Aig_Obj_t * pFanin, * pTemp;
|
||||
int LevelOld, LevFanin, Lev, k;
|
||||
assert( p->vLevelR != NULL );
|
||||
assert( Aig_ObjIsNode(pObjNew) );
|
||||
// allocate level if needed
|
||||
if ( p->vLevels == NULL )
|
||||
p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 );
|
||||
// check if level has changed
|
||||
LevelOld = Aig_ObjReverseLevel(p, pObjNew);
|
||||
if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) )
|
||||
return;
|
||||
// start the data structure for level update
|
||||
// we cannot fail to visit a node when using this structure because the
|
||||
// nodes are stored by their _old_ levels, which are assumed to be correct
|
||||
Vec_VecClear( p->vLevels );
|
||||
Vec_VecPush( p->vLevels, LevelOld, pObjNew );
|
||||
pObjNew->fMarkA = 1;
|
||||
// recursively update level
|
||||
Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld )
|
||||
{
|
||||
pTemp->fMarkA = 0;
|
||||
LevelOld = Aig_ObjReverseLevel(p, pTemp);
|
||||
assert( LevelOld == Lev );
|
||||
Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) );
|
||||
// if the level did not change, to need to check the fanout levels
|
||||
if ( Aig_ObjReverseLevel(p, pTemp) == Lev )
|
||||
continue;
|
||||
// schedule fanins for level update
|
||||
pFanin = Aig_ObjFanin0(pTemp);
|
||||
if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA )
|
||||
{
|
||||
LevFanin = Aig_ObjReverseLevel( p, pFanin );
|
||||
assert( LevFanin >= Lev );
|
||||
Vec_VecPush( p->vLevels, LevFanin, pFanin );
|
||||
pFanin->fMarkA = 1;
|
||||
}
|
||||
pFanin = Aig_ObjFanin1(pTemp);
|
||||
if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA )
|
||||
{
|
||||
LevFanin = Aig_ObjReverseLevel( p, pFanin );
|
||||
assert( LevFanin >= Lev );
|
||||
Vec_VecPush( p->vLevels, LevFanin, pFanin );
|
||||
pFanin->fMarkA = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Verifies direct level of the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManVerifyLevel( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i, Counter = 0;
|
||||
assert( p->pFanData );
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) )
|
||||
{
|
||||
printf( "Level of node %6d should be %4d instead of %4d.\n",
|
||||
pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) );
|
||||
Counter++;
|
||||
}
|
||||
if ( Counter )
|
||||
printf( "Levels of %d nodes are incorrect.\n", Counter );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Verifies reverse level of the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManVerifyReverseLevel( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i, Counter = 0;
|
||||
assert( p->vLevelR );
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) )
|
||||
{
|
||||
printf( "Reverse level of node %6d should be %4d instead of %4d.\n",
|
||||
pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) );
|
||||
Counter++;
|
||||
}
|
||||
if ( Counter )
|
||||
printf( "Reverse levels of %d nodes are incorrect.\n", Counter );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigTruth.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Computes truth table for the cut.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords )
|
||||
{
|
||||
unsigned * pTruth0, * pTruth1;
|
||||
int i;
|
||||
pTruth0 = Aig_ObjFanin0(pNode)->pData;
|
||||
pTruth1 = Aig_ObjFanin1(pNode)->pData;
|
||||
if ( Aig_ObjIsExor(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] ^ pTruth1[i];
|
||||
else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] & pTruth1[i];
|
||||
else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] & ~pTruth1[i];
|
||||
else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = ~pTruth0[i] & pTruth1[i];
|
||||
else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
|
||||
return pTruth;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description [The returned pointer should be used immediately.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i, nWords;
|
||||
assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) );
|
||||
assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) );
|
||||
assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) );
|
||||
// assign elementary truth tables
|
||||
Vec_PtrForEachEntry( vLeaves, pObj, i )
|
||||
pObj->pData = Vec_PtrEntry( vTruthElem, i );
|
||||
// compute truths for other nodes
|
||||
nWords = Aig_TruthWordNum( Vec_PtrSize(vLeaves) );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
pObj->pData = Aig_ManCutTruthOne( pObj, Vec_PtrEntry(vTruthStore, i), nWords );
|
||||
return pRoot->pData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,732 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigUtil.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Various procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis [Returns the next prime >= p.]
|
||||
|
||||
Description [Copied from CUDD, for stand-aloneness.]
|
||||
|
||||
SideEffects [None]
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
unsigned int Aig_PrimeCudd( unsigned int p )
|
||||
{
|
||||
int i,pn;
|
||||
|
||||
p--;
|
||||
do {
|
||||
p++;
|
||||
if (p&1) {
|
||||
pn = 1;
|
||||
i = 3;
|
||||
while ((unsigned) (i * i) <= p) {
|
||||
if (p % i == 0) {
|
||||
pn = 0;
|
||||
break;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
} else {
|
||||
pn = 0;
|
||||
}
|
||||
} while (!pn);
|
||||
return(p);
|
||||
|
||||
} /* end of Cudd_Prime */
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Increments the current traversal ID of the network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManIncrementTravId( Aig_Man_t * p )
|
||||
{
|
||||
if ( p->nTravIds >= (1<<30)-1 )
|
||||
Aig_ManCleanData( p );
|
||||
p->nTravIds++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collect the latches.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManLevels( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i, LevelMax = 0;
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
LevelMax = AIG_MAX( LevelMax, (int)Aig_ObjFanin0(pObj)->Level );
|
||||
return LevelMax;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reset reference counters.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManResetRefs( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
pObj->nRefs = 0;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjFanin0(pObj) )
|
||||
Aig_ObjFanin0(pObj)->nRefs++;
|
||||
if ( Aig_ObjFanin1(pObj) )
|
||||
Aig_ObjFanin1(pObj)->nRefs++;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Cleans MarkB.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCleanMarkA( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
pObj->fMarkA = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Cleans MarkB.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCleanMarkB( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
pObj->fMarkB = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Cleans the data pointers for the nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCleanData( Aig_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
pObj->pData = NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recursively cleans the data pointers in the cone of the node.]
|
||||
|
||||
Description [Applicable to small AIGs only because no caching is performed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCleanData_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( !Aig_ObjIsPo(pObj) );
|
||||
if ( Aig_ObjIsAnd(pObj) )
|
||||
{
|
||||
Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) );
|
||||
Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) );
|
||||
}
|
||||
pObj->pData = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Detects multi-input gate rooted at this node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
|
||||
{
|
||||
if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) )
|
||||
{
|
||||
Vec_PtrPushUnique(vSuper, pObj);
|
||||
return;
|
||||
}
|
||||
Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper );
|
||||
Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Detects multi-input gate rooted at this node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper )
|
||||
{
|
||||
assert( !Aig_IsComplement(pRoot) );
|
||||
Vec_PtrClear( vSuper );
|
||||
Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjIsMuxType( Aig_Obj_t * pNode )
|
||||
{
|
||||
Aig_Obj_t * pNode0, * pNode1;
|
||||
// check that the node is regular
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
// if the node is not AND, this is not MUX
|
||||
if ( !Aig_ObjIsAnd(pNode) )
|
||||
return 0;
|
||||
// if the children are not complemented, this is not MUX
|
||||
if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) )
|
||||
return 0;
|
||||
// get children
|
||||
pNode0 = Aig_ObjFanin0(pNode);
|
||||
pNode1 = Aig_ObjFanin1(pNode);
|
||||
// if the children are not ANDs, this is not MUX
|
||||
if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) )
|
||||
return 0;
|
||||
// otherwise the node is MUX iff it has a pair of equal grandchildren
|
||||
return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) ||
|
||||
(Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) ||
|
||||
(Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) ||
|
||||
(Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)));
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recognizes what nodes are inputs of the EXOR.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 )
|
||||
{
|
||||
Aig_Obj_t * p0, * p1;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
return 0;
|
||||
if ( Aig_ObjIsExor(pObj) )
|
||||
{
|
||||
*ppFan0 = Aig_ObjChild0(pObj);
|
||||
*ppFan1 = Aig_ObjChild1(pObj);
|
||||
return 1;
|
||||
}
|
||||
assert( Aig_ObjIsAnd(pObj) );
|
||||
p0 = Aig_ObjChild0(pObj);
|
||||
p1 = Aig_ObjChild1(pObj);
|
||||
if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) )
|
||||
return 0;
|
||||
p0 = Aig_Regular(p0);
|
||||
p1 = Aig_Regular(p1);
|
||||
if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) )
|
||||
return 0;
|
||||
if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) )
|
||||
return 0;
|
||||
if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) )
|
||||
return 0;
|
||||
*ppFan0 = Aig_ObjChild0(p0);
|
||||
*ppFan1 = Aig_ObjChild1(p0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
|
||||
|
||||
Description [If the node is a MUX, returns the control variable C.
|
||||
Assigns nodes T and E to be the then and else variables of the MUX.
|
||||
Node C is never complemented. Nodes T and E can be complemented.
|
||||
This function also recognizes EXOR/NEXOR gates as MUXes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE )
|
||||
{
|
||||
Aig_Obj_t * pNode0, * pNode1;
|
||||
assert( !Aig_IsComplement(pNode) );
|
||||
assert( Aig_ObjIsMuxType(pNode) );
|
||||
// get children
|
||||
pNode0 = Aig_ObjFanin0(pNode);
|
||||
pNode1 = Aig_ObjFanin1(pNode);
|
||||
|
||||
// find the control variable
|
||||
if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) )
|
||||
{
|
||||
// if ( Fraig_IsComplement(pNode1->p2) )
|
||||
if ( Aig_ObjFaninC1(pNode0) )
|
||||
{ // pNode2->p2 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
|
||||
return Aig_ObjChild1(pNode1);//pNode2->p2;
|
||||
}
|
||||
else
|
||||
{ // pNode1->p2 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
|
||||
return Aig_ObjChild1(pNode0);//pNode1->p2;
|
||||
}
|
||||
}
|
||||
else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) )
|
||||
{
|
||||
// if ( Fraig_IsComplement(pNode1->p1) )
|
||||
if ( Aig_ObjFaninC0(pNode0) )
|
||||
{ // pNode2->p1 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
|
||||
return Aig_ObjChild0(pNode1);//pNode2->p1;
|
||||
}
|
||||
else
|
||||
{ // pNode1->p1 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
|
||||
return Aig_ObjChild0(pNode0);//pNode1->p1;
|
||||
}
|
||||
}
|
||||
else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) )
|
||||
{
|
||||
// if ( Fraig_IsComplement(pNode1->p1) )
|
||||
if ( Aig_ObjFaninC0(pNode0) )
|
||||
{ // pNode2->p2 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
|
||||
return Aig_ObjChild1(pNode1);//pNode2->p2;
|
||||
}
|
||||
else
|
||||
{ // pNode1->p1 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
|
||||
return Aig_ObjChild0(pNode0);//pNode1->p1;
|
||||
}
|
||||
}
|
||||
else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) )
|
||||
{
|
||||
// if ( Fraig_IsComplement(pNode1->p2) )
|
||||
if ( Aig_ObjFaninC1(pNode0) )
|
||||
{ // pNode2->p1 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
|
||||
return Aig_ObjChild0(pNode1);//pNode2->p1;
|
||||
}
|
||||
else
|
||||
{ // pNode1->p2 is positive phase of C
|
||||
*ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
|
||||
*ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
|
||||
return Aig_ObjChild1(pNode0);//pNode1->p2;
|
||||
}
|
||||
}
|
||||
assert( 0 ); // this is not MUX
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj);
|
||||
if ( !Aig_ObjIsBuf(pObjR) )
|
||||
return pObj;
|
||||
pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) );
|
||||
return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints Eqn formula for the AIG rooted at this node.]
|
||||
|
||||
Description [The formula is in terms of PIs, which should have
|
||||
their names assigned in pObj->pData fields.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
|
||||
{
|
||||
Vec_Ptr_t * vSuper;
|
||||
Aig_Obj_t * pFanin;
|
||||
int fCompl, i;
|
||||
// store the complemented attribute
|
||||
fCompl = Aig_IsComplement(pObj);
|
||||
pObj = Aig_Regular(pObj);
|
||||
// constant case
|
||||
if ( Aig_ObjIsConst1(pObj) )
|
||||
{
|
||||
fprintf( pFile, "%d", !fCompl );
|
||||
return;
|
||||
}
|
||||
// PI case
|
||||
if ( Aig_ObjIsPi(pObj) )
|
||||
{
|
||||
fprintf( pFile, "%s%s", fCompl? "!" : "", pObj->pData );
|
||||
return;
|
||||
}
|
||||
// AND case
|
||||
Vec_VecExpand( vLevels, Level );
|
||||
vSuper = Vec_VecEntry(vLevels, Level);
|
||||
Aig_ObjCollectMulti( pObj, vSuper );
|
||||
fprintf( pFile, "%s", (Level==0? "" : "(") );
|
||||
Vec_PtrForEachEntry( vSuper, pFanin, i )
|
||||
{
|
||||
Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 );
|
||||
if ( i < Vec_PtrSize(vSuper) - 1 )
|
||||
fprintf( pFile, " %s ", fCompl? "+" : "*" );
|
||||
}
|
||||
fprintf( pFile, "%s", (Level==0? "" : ")") );
|
||||
return;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints Verilog formula for the AIG rooted at this node.]
|
||||
|
||||
Description [The formula is in terms of PIs, which should have
|
||||
their names assigned in pObj->pData fields.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
|
||||
{
|
||||
Vec_Ptr_t * vSuper;
|
||||
Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC;
|
||||
int fCompl, i;
|
||||
// store the complemented attribute
|
||||
fCompl = Aig_IsComplement(pObj);
|
||||
pObj = Aig_Regular(pObj);
|
||||
// constant case
|
||||
if ( Aig_ObjIsConst1(pObj) )
|
||||
{
|
||||
fprintf( pFile, "1\'b%d", !fCompl );
|
||||
return;
|
||||
}
|
||||
// PI case
|
||||
if ( Aig_ObjIsPi(pObj) )
|
||||
{
|
||||
fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData );
|
||||
return;
|
||||
}
|
||||
// EXOR case
|
||||
if ( Aig_ObjIsExor(pObj) )
|
||||
{
|
||||
Vec_VecExpand( vLevels, Level );
|
||||
vSuper = Vec_VecEntry( vLevels, Level );
|
||||
Aig_ObjCollectMulti( pObj, vSuper );
|
||||
fprintf( pFile, "%s", (Level==0? "" : "(") );
|
||||
Vec_PtrForEachEntry( vSuper, pFanin, i )
|
||||
{
|
||||
Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 );
|
||||
if ( i < Vec_PtrSize(vSuper) - 1 )
|
||||
fprintf( pFile, " ^ " );
|
||||
}
|
||||
fprintf( pFile, "%s", (Level==0? "" : ")") );
|
||||
return;
|
||||
}
|
||||
// MUX case
|
||||
if ( Aig_ObjIsMuxType(pObj) )
|
||||
{
|
||||
if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) )
|
||||
{
|
||||
fprintf( pFile, "%s", (Level==0? "" : "(") );
|
||||
Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 );
|
||||
fprintf( pFile, " ^ " );
|
||||
Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 );
|
||||
fprintf( pFile, "%s", (Level==0? "" : ")") );
|
||||
}
|
||||
else
|
||||
{
|
||||
pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 );
|
||||
fprintf( pFile, "%s", (Level==0? "" : "(") );
|
||||
Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 );
|
||||
fprintf( pFile, " ? " );
|
||||
Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 );
|
||||
fprintf( pFile, " : " );
|
||||
Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 );
|
||||
fprintf( pFile, "%s", (Level==0? "" : ")") );
|
||||
}
|
||||
return;
|
||||
}
|
||||
// AND case
|
||||
Vec_VecExpand( vLevels, Level );
|
||||
vSuper = Vec_VecEntry(vLevels, Level);
|
||||
Aig_ObjCollectMulti( pObj, vSuper );
|
||||
fprintf( pFile, "%s", (Level==0? "" : "(") );
|
||||
Vec_PtrForEachEntry( vSuper, pFanin, i )
|
||||
{
|
||||
Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 );
|
||||
if ( i < Vec_PtrSize(vSuper) - 1 )
|
||||
fprintf( pFile, " %s ", fCompl? "|" : "&" );
|
||||
}
|
||||
fprintf( pFile, "%s", (Level==0? "" : ")") );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints node in HAIG.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig )
|
||||
{
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
printf( "Node %p : ", pObj );
|
||||
if ( Aig_ObjIsConst1(pObj) )
|
||||
printf( "constant 1" );
|
||||
else if ( Aig_ObjIsPi(pObj) )
|
||||
printf( "PI" );
|
||||
else
|
||||
printf( "AND( %p%s, %p%s )",
|
||||
Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "),
|
||||
Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") );
|
||||
printf( " (refs = %3d)", Aig_ObjRefs(pObj) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints node in HAIG.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
printf( "PIs: " );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
printf( " %p", pObj );
|
||||
printf( "\n" );
|
||||
vNodes = Aig_ManDfs( p );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Write speculative miter for one node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDump( Aig_Man_t * p )
|
||||
{
|
||||
static int Counter = 0;
|
||||
char FileName[20];
|
||||
// dump the logic into a file
|
||||
sprintf( FileName, "aigbug\\%03d.blif", ++Counter );
|
||||
Aig_ManDumpBlif( p, FileName );
|
||||
printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes the AIG into the BLIF file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName )
|
||||
{
|
||||
FILE * pFile;
|
||||
Vec_Ptr_t * vNodes;
|
||||
Aig_Obj_t * pObj, * pConst1 = NULL;
|
||||
int i, nDigits, Counter = 0;
|
||||
if ( Aig_ManPoNum(p) == 0 )
|
||||
{
|
||||
printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" );
|
||||
return;
|
||||
}
|
||||
// collect nodes in the DFS order
|
||||
vNodes = Aig_ManDfs( p );
|
||||
// assign IDs to objects
|
||||
Aig_ManConst1(p)->pData = (void *)Counter++;
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = (void *)Counter++;
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
pObj->pData = (void *)Counter++;
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
pObj->pData = (void *)Counter++;
|
||||
nDigits = Extra_Base10Log( Counter );
|
||||
// write the file
|
||||
pFile = fopen( pFileName, "w" );
|
||||
fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif() in ABC\n" );
|
||||
fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" );
|
||||
fprintf( pFile, ".model test\n" );
|
||||
// write PIs
|
||||
fprintf( pFile, ".inputs" );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData );
|
||||
fprintf( pFile, "\n" );
|
||||
// write POs
|
||||
fprintf( pFile, ".outputs" );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData );
|
||||
fprintf( pFile, "\n" );
|
||||
// write nodes
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
{
|
||||
fprintf( pFile, ".names n%0*d n%0*d n%0*d\n",
|
||||
nDigits, (int)Aig_ObjFanin0(pObj)->pData,
|
||||
nDigits, (int)Aig_ObjFanin1(pObj)->pData,
|
||||
nDigits, (int)pObj->pData );
|
||||
fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) );
|
||||
}
|
||||
// write POs
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
{
|
||||
if ( (int)pObj->pData == 1359 )
|
||||
{
|
||||
int x = 0;
|
||||
}
|
||||
fprintf( pFile, ".names n%0*d n%0*d\n",
|
||||
nDigits, (int)Aig_ObjFanin0(pObj)->pData,
|
||||
nDigits, (int)pObj->pData );
|
||||
fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) );
|
||||
if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
|
||||
pConst1 = Aig_ManConst1(p);
|
||||
}
|
||||
if ( pConst1 )
|
||||
fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
fclose( pFile );
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aigWin.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis [Window computation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluate the cost of removing the node from the set of leaves.]
|
||||
|
||||
Description [Returns the number of new leaves that will be brought in.
|
||||
Returns large number if the node cannot be removed from the set of leaves.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit )
|
||||
{
|
||||
int Cost;
|
||||
// make sure the node is in the construction zone
|
||||
assert( pNode->fMarkA );
|
||||
// cannot expand over the PI node
|
||||
if ( Aig_ObjIsPi(pNode) )
|
||||
return 999;
|
||||
// get the cost of the cone
|
||||
Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA);
|
||||
// always accept if the number of leaves does not increase
|
||||
if ( Cost < 2 )
|
||||
return Cost;
|
||||
// skip nodes with many fanouts
|
||||
if ( (int)pNode->nRefs > nFanoutLimit )
|
||||
return 999;
|
||||
// return the number of nodes that will be on the leaves if this node is removed
|
||||
return Cost;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
|
||||
|
||||
Description [This procedure looks at the current leaves and tries to change
|
||||
one leaf at a time in such a way that the cut grows as little as possible.
|
||||
In evaluating the fanins, this procedure looks only at their immediate
|
||||
predecessors (this is why it is called a one-level construction procedure).]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit )
|
||||
{
|
||||
Aig_Obj_t * pNode, * pFaninBest, * pNext;
|
||||
int CostBest, CostCur, i;
|
||||
// find the best fanin
|
||||
CostBest = 100;
|
||||
pFaninBest = NULL;
|
||||
//printf( "Evaluating fanins of the cut:\n" );
|
||||
Vec_PtrForEachEntry( vFront, pNode, i )
|
||||
{
|
||||
CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit );
|
||||
//printf( " Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur );
|
||||
if ( CostBest > CostCur ||
|
||||
(CostBest == CostCur && pNode->Level > pFaninBest->Level) )
|
||||
{
|
||||
CostBest = CostCur;
|
||||
pFaninBest = pNode;
|
||||
}
|
||||
if ( CostBest == 0 )
|
||||
break;
|
||||
}
|
||||
if ( pFaninBest == NULL )
|
||||
return 0;
|
||||
assert( CostBest < 3 );
|
||||
if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit )
|
||||
return 0;
|
||||
assert( Aig_ObjIsNode(pFaninBest) );
|
||||
// remove the node from the array
|
||||
Vec_PtrRemove( vFront, pFaninBest );
|
||||
//printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) );
|
||||
|
||||
// add the left child to the fanins
|
||||
pNext = Aig_ObjFanin0(pFaninBest);
|
||||
if ( !pNext->fMarkA )
|
||||
{
|
||||
//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) );
|
||||
pNext->fMarkA = 1;
|
||||
Vec_PtrPush( vFront, pNext );
|
||||
Vec_PtrPush( vVisited, pNext );
|
||||
}
|
||||
// add the right child to the fanins
|
||||
pNext = Aig_ObjFanin1(pFaninBest);
|
||||
if ( !pNext->fMarkA )
|
||||
{
|
||||
//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) );
|
||||
pNext->fMarkA = 1;
|
||||
Vec_PtrPush( vFront, pNext );
|
||||
Vec_PtrPush( vVisited, pNext );
|
||||
}
|
||||
assert( Vec_PtrSize(vFront) <= nSizeLimit );
|
||||
// keep doing this
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes one sequential cut of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit )
|
||||
{
|
||||
Aig_Obj_t * pNode;
|
||||
int i;
|
||||
|
||||
assert( !Aig_IsComplement(pRoot) );
|
||||
assert( Aig_ObjIsNode(pRoot) );
|
||||
assert( Aig_ObjChild0(pRoot) );
|
||||
assert( Aig_ObjChild1(pRoot) );
|
||||
|
||||
// start the cut
|
||||
Vec_PtrClear( vFront );
|
||||
Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) );
|
||||
Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) );
|
||||
|
||||
// start the visited nodes
|
||||
Vec_PtrClear( vVisited );
|
||||
Vec_PtrPush( vVisited, pRoot );
|
||||
Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) );
|
||||
Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) );
|
||||
|
||||
// mark these nodes
|
||||
assert( !pRoot->fMarkA );
|
||||
assert( !Aig_ObjFanin0(pRoot)->fMarkA );
|
||||
assert( !Aig_ObjFanin1(pRoot)->fMarkA );
|
||||
pRoot->fMarkA = 1;
|
||||
Aig_ObjFanin0(pRoot)->fMarkA = 1;
|
||||
Aig_ObjFanin1(pRoot)->fMarkA = 1;
|
||||
|
||||
// compute the cut
|
||||
while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) );
|
||||
assert( Vec_PtrSize(vFront) <= nSizeLimit );
|
||||
|
||||
// clean the visit markings
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
pNode->fMarkA = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [aig_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG package.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "aig.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
SRC += src/aig/aig/aigCheck.c \
|
||||
src/aig/aig/aigDfs.c \
|
||||
src/aig/aig/aigFanout.c \
|
||||
src/aig/aig/aigMan.c \
|
||||
src/aig/aig/aigMem.c \
|
||||
src/aig/aig/aigMffc.c \
|
||||
src/aig/aig/aigObj.c \
|
||||
src/aig/aig/aigOper.c \
|
||||
src/aig/aig/aigOrder.c \
|
||||
src/aig/aig/aigPart.c \
|
||||
src/aig/aig/aigRepr.c \
|
||||
src/aig/aig/aigSeq.c \
|
||||
src/aig/aig/aigTable.c \
|
||||
src/aig/aig/aigTiming.c \
|
||||
src/aig/aig/aigTruth.c \
|
||||
src/aig/aig/aigUtil.c \
|
||||
src/aig/aig/aigWin.c
|
|
@ -0,0 +1,73 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdc.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 30, 2007.]
|
||||
|
||||
Revision [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __BDC_H__
|
||||
#define __BDC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Bdc_Man_t_ Bdc_Man_t;
|
||||
typedef struct Bdc_Par_t_ Bdc_Par_t;
|
||||
struct Bdc_Par_t_
|
||||
{
|
||||
// general parameters
|
||||
int nVarsMax; // the maximum support
|
||||
int fVerbose; // enable basic stats
|
||||
int fVeryVerbose; // enable detailed stats
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== bdcCore.c ==========================================================*/
|
||||
extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars );
|
||||
extern void Bdc_ManFree( Bdc_Man_t * p );
|
||||
extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesLimit );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdcCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis [The gateway to bi-decomposition.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 30, 2007.]
|
||||
|
||||
Revision [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bdcInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocate resynthesis manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars )
|
||||
{
|
||||
Bdc_Man_t * p;
|
||||
unsigned * pData;
|
||||
int i, k, nBits;
|
||||
p = ALLOC( Bdc_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Bdc_Man_t) );
|
||||
assert( pPars->nVarsMax > 3 && pPars->nVarsMax < 16 );
|
||||
p->pPars = pPars;
|
||||
p->nWords = Kit_TruthWordNum( pPars->nVarsMax );
|
||||
p->nDivsLimit = 200;
|
||||
p->nNodesLimit = 0; // will be set later
|
||||
// memory
|
||||
p->vMemory = Vec_IntStart( 1 << 16 );
|
||||
// internal nodes
|
||||
p->nNodesAlloc = 512;
|
||||
p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc );
|
||||
// set up hash table
|
||||
p->nTableSize = (1 << p->pPars->nVarsMax);
|
||||
p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize );
|
||||
memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize );
|
||||
p->vSpots = Vec_IntAlloc( 256 );
|
||||
// truth tables
|
||||
p->vTruths = Vec_PtrAllocSimInfo( pPars->nVarsMax + 5, p->nWords );
|
||||
// set elementary truth tables
|
||||
nBits = (1 << pPars->nVarsMax);
|
||||
Kit_TruthFill( Vec_PtrEntry(p->vTruths, 0), p->nVars );
|
||||
for ( k = 0; k < pPars->nVarsMax; k++ )
|
||||
{
|
||||
pData = Vec_PtrEntry( p->vTruths, k+1 );
|
||||
Kit_TruthClear( pData, p->nVars );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
if ( i & (1 << k) )
|
||||
pData[i>>5] |= (1 << (i&31));
|
||||
}
|
||||
p->puTemp1 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 1 );
|
||||
p->puTemp2 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 2 );
|
||||
p->puTemp3 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 3 );
|
||||
p->puTemp4 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 4 );
|
||||
// start the internal ISFs
|
||||
p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL );
|
||||
p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR );
|
||||
p->pIsfAL = &p->IsfAL; Bdc_IsfStart( p, p->pIsfAL );
|
||||
p->pIsfAR = &p->IsfAR; Bdc_IsfStart( p, p->pIsfAR );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deallocate resynthesis manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bdc_ManFree( Bdc_Man_t * p )
|
||||
{
|
||||
Vec_IntFree( p->vMemory );
|
||||
Vec_IntFree( p->vSpots );
|
||||
Vec_PtrFree( p->vTruths );
|
||||
free( p->pNodes );
|
||||
free( p->pTable );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Clears the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs )
|
||||
{
|
||||
unsigned * puTruth;
|
||||
Bdc_Fun_t * pNode;
|
||||
int i;
|
||||
Bdc_TableClear( p );
|
||||
Vec_IntClear( p->vMemory );
|
||||
// add constant 1 and elementary vars
|
||||
p->nNodes = p->nNodesNew = 0;
|
||||
for ( i = 0; i <= p->pPars->nVarsMax; i++ )
|
||||
{
|
||||
pNode = Bdc_FunNew( p );
|
||||
pNode->Type = BDC_TYPE_PI;
|
||||
pNode->puFunc = Vec_PtrEntry( p->vTruths, i );
|
||||
pNode->uSupp = i? (1 << (i-1)) : 0;
|
||||
Bdc_TableAdd( p, pNode );
|
||||
}
|
||||
// add the divisors
|
||||
Vec_PtrForEachEntry( vDivs, puTruth, i )
|
||||
{
|
||||
pNode = Bdc_FunNew( p );
|
||||
pNode->Type = BDC_TYPE_PI;
|
||||
pNode->puFunc = puTruth;
|
||||
pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars );
|
||||
Bdc_TableAdd( p, pNode );
|
||||
if ( i == p->nDivsLimit )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs decomposition of one function.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax )
|
||||
{
|
||||
Bdc_Isf_t Isf, * pIsf = &Isf;
|
||||
// set current manager parameters
|
||||
p->nVars = nVars;
|
||||
p->nWords = Kit_TruthWordNum( nVars );
|
||||
Bdc_ManPrepare( p, vDivs );
|
||||
p->nNodesLimit = (p->nNodes + nNodesMax < p->nNodesAlloc)? p->nNodes + nNodesMax : p->nNodesAlloc;
|
||||
// copy the function
|
||||
Bdc_IsfStart( p, pIsf );
|
||||
Bdc_IsfClean( pIsf );
|
||||
pIsf->uSupp = Kit_TruthSupport( puFunc, p->nVars ) | Kit_TruthSupport( puCare, p->nVars );
|
||||
Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars );
|
||||
Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars );
|
||||
// call decomposition
|
||||
Bdc_SuppMinimize( p, pIsf );
|
||||
p->pRoot = Bdc_ManDecompose_rec( p, pIsf );
|
||||
if ( p->pRoot == NULL )
|
||||
return -1;
|
||||
return p->nNodesNew;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,461 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdcDec.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis [Decomposition procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 30, 2007.]
|
||||
|
||||
Revision [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bdcInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR );
|
||||
static int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs one step of bi-decomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
|
||||
{
|
||||
Bdc_Fun_t * pFunc;
|
||||
Bdc_Isf_t IsfL, * pIsfL = &IsfL;
|
||||
Bdc_Isf_t IsfB, * pIsfR = &IsfB;
|
||||
// check computed results
|
||||
if ( pFunc = Bdc_TableLookup( p, pIsf ) )
|
||||
return pFunc;
|
||||
// decide on the decomposition type
|
||||
pFunc = Bdc_FunNew( p );
|
||||
if ( pFunc == NULL )
|
||||
return NULL;
|
||||
pFunc->Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR );
|
||||
// decompose the left branch
|
||||
pFunc->pFan0 = Bdc_ManDecompose_rec( p, pIsfL );
|
||||
if ( pFunc->pFan0 == NULL )
|
||||
return NULL;
|
||||
// decompose the right branch
|
||||
if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc->pFan0->puFunc, pFunc->Type ) )
|
||||
{
|
||||
p->nNodes--;
|
||||
return pFunc->pFan0;
|
||||
}
|
||||
pFunc->pFan1 = Bdc_ManDecompose_rec( p, pIsfL );
|
||||
if ( pFunc->pFan1 == NULL )
|
||||
return NULL;
|
||||
// compute the function of node
|
||||
pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords);
|
||||
if ( pFunc->Type == BDC_TYPE_AND )
|
||||
Kit_TruthAnd( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars );
|
||||
else if ( pFunc->Type == BDC_TYPE_OR )
|
||||
Kit_TruthOr( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars );
|
||||
else
|
||||
assert( 0 );
|
||||
// verify correctness
|
||||
assert( Bdc_TableCheckContainment(p, pIsf, pFunc->puFunc) );
|
||||
// convert from OR to AND
|
||||
if ( pFunc->Type == BDC_TYPE_OR )
|
||||
{
|
||||
pFunc->Type = BDC_TYPE_AND;
|
||||
pFunc->pFan0 = Bdc_Not(pFunc->pFan0);
|
||||
pFunc->pFan1 = Bdc_Not(pFunc->pFan1);
|
||||
Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars );
|
||||
pFunc = Bdc_Not(pFunc);
|
||||
}
|
||||
Bdc_TableAdd( p, Bdc_Regular(pFunc) );
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Updates the ISF of the right after the left was decompoosed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type )
|
||||
{
|
||||
if ( Type == BDC_TYPE_OR )
|
||||
{
|
||||
// Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes );
|
||||
// Right.R = bdd_exist( R, setRightRes );
|
||||
|
||||
// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q );
|
||||
// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R );
|
||||
// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V ); Cudd_Ref( pR->Q );
|
||||
// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R );
|
||||
|
||||
// assert( pR->R != b0 );
|
||||
// return (int)( pR->Q == b0 );
|
||||
|
||||
Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars );
|
||||
Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
|
||||
Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp );
|
||||
assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
|
||||
return Kit_TruthIsConst0(pIsfR->puOn, p->nVars);
|
||||
}
|
||||
else if ( Type == BDC_TYPE_AND )
|
||||
{
|
||||
// Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes );
|
||||
// Right.Q = bdd_exist( Q, setRightRes );
|
||||
|
||||
// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q );
|
||||
// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R );
|
||||
// pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V ); Cudd_Ref( pR->R );
|
||||
// pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V ); Cudd_Ref( pR->Q );
|
||||
|
||||
// assert( pR->Q != b0 );
|
||||
// return (int)( pR->R == b0 );
|
||||
|
||||
Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars );
|
||||
Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
|
||||
Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp );
|
||||
assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
|
||||
return Kit_TruthIsConst0(pIsfR->puOn, p->nVars);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks existence of OR-bidecomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars )
|
||||
{
|
||||
assert( nLeftVars > 0 );
|
||||
assert( nRightVars > 0 );
|
||||
// compute the decomposition coefficient
|
||||
if ( nLeftVars >= nRightVars )
|
||||
return BDC_SCALE * (p->nVars * nRightVars + nLeftVars);
|
||||
else // if ( nLeftVars < nRightVars )
|
||||
return BDC_SCALE * (p->nVars * nLeftVars + nRightVars);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks existence of weak OR-bidecomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
|
||||
{
|
||||
char pVars[16];
|
||||
int v, nVars, Beg, End;
|
||||
|
||||
assert( pIsfL->uSupp == 0 );
|
||||
assert( pIsfR->uSupp == 0 );
|
||||
|
||||
// fill in the variables
|
||||
nVars = 0;
|
||||
for ( v = 0; v < p->nVars; v++ )
|
||||
if ( pIsf->uSupp & (1 << v) )
|
||||
pVars[nVars++] = v;
|
||||
|
||||
// try variable pairs
|
||||
for ( Beg = 0; Beg < nVars; Beg++ )
|
||||
{
|
||||
Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] );
|
||||
for ( End = nVars - 1; End > Beg; End-- )
|
||||
{
|
||||
Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] );
|
||||
if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) )
|
||||
{
|
||||
pIsfL->uSupp = (1 << Beg);
|
||||
pIsfR->uSupp = (1 << End);
|
||||
pIsfL->Var = Beg;
|
||||
pIsfR->Var = End;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks existence of weak OR-bidecomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
|
||||
{
|
||||
int v, VarCost, VarBest, Cost, VarCostBest = 0;
|
||||
|
||||
for ( v = 0; v < p->nVars; v++ )
|
||||
{
|
||||
Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v );
|
||||
// if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse )
|
||||
// Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist );
|
||||
// if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 )
|
||||
if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) )
|
||||
{
|
||||
// measure the cost of this variable
|
||||
// VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube );
|
||||
|
||||
// Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ );
|
||||
// VarCost = Kit_TruthCountOnes( Univ, p->nVars );
|
||||
// Cudd_RecursiveDeref( dd, Univ );
|
||||
|
||||
Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v );
|
||||
VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars );
|
||||
if ( VarCost == 0 )
|
||||
VarCost = 1;
|
||||
if ( VarCostBest < VarCost )
|
||||
{
|
||||
VarCostBest = VarCost;
|
||||
VarBest = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// derive the components for weak-bi-decomposition if the variable is found
|
||||
if ( VarCostBest )
|
||||
{
|
||||
// funQLeftRes = Q & bdd_exist( R, setRightORweak );
|
||||
|
||||
// Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp );
|
||||
// pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q );
|
||||
// Cudd_RecursiveDeref( dd, Temp );
|
||||
|
||||
Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest );
|
||||
Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
|
||||
|
||||
// pL->R = pF->R; Cudd_Ref( pL->R );
|
||||
// pL->V = VarBest; Cudd_Ref( pL->V );
|
||||
Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars );
|
||||
pIsfL->Var = VarBest;
|
||||
|
||||
// assert( pL->Q != b0 );
|
||||
// assert( pL->R != b0 );
|
||||
// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
|
||||
|
||||
// express cost in percents of the covered boolean space
|
||||
Cost = VarCostBest * BDC_SCALE / (1<<p->nVars);
|
||||
if ( Cost == 0 )
|
||||
Cost = 1;
|
||||
return Cost;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks existence of OR-bidecomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
|
||||
{
|
||||
unsigned uSuppRem;
|
||||
int v, nLeftVars = 1, nRightVars = 1;
|
||||
// clean the var sets
|
||||
Bdc_IsfClean( pIsfL );
|
||||
Bdc_IsfClean( pIsfR );
|
||||
// find initial variable sets
|
||||
if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) )
|
||||
return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR );
|
||||
// prequantify the variables in the offset
|
||||
Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->Var );
|
||||
Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->Var );
|
||||
// go through the remaining variables
|
||||
uSuppRem = pIsf->uSupp & ~pIsfL->uSupp & ~pIsfR->uSupp;
|
||||
assert( Kit_WordCountOnes(uSuppRem) > 0 );
|
||||
for ( v = 0; v < p->nVars; v++ )
|
||||
{
|
||||
if ( (uSuppRem & (1 << v)) == 0 )
|
||||
continue;
|
||||
// prequantify this variable
|
||||
Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v );
|
||||
Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v );
|
||||
if ( nLeftVars < nRightVars )
|
||||
{
|
||||
// if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
|
||||
// if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) )
|
||||
if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
|
||||
{
|
||||
// pL->V &= VarNew;
|
||||
pIsfL->uSupp |= (1 << v);
|
||||
nLeftVars++;
|
||||
}
|
||||
// else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
|
||||
else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
|
||||
{
|
||||
// pR->V &= VarNew;
|
||||
pIsfR->uSupp |= (1 << v);
|
||||
nRightVars++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
|
||||
if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
|
||||
{
|
||||
// pR->V &= VarNew;
|
||||
pIsfR->uSupp |= (1 << v);
|
||||
nRightVars++;
|
||||
}
|
||||
// else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
|
||||
else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
|
||||
{
|
||||
// pL->V &= VarNew;
|
||||
pIsfL->uSupp |= (1 << v);
|
||||
nLeftVars++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// derive the functions Q and R for the left branch
|
||||
// pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V );
|
||||
// pL->R = bdd_exist( pF->R, pR->V );
|
||||
|
||||
// Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( Temp );
|
||||
// pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q );
|
||||
// Cudd_RecursiveDeref( dd, Temp );
|
||||
// pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R );
|
||||
|
||||
Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
|
||||
Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uSupp );
|
||||
Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars );
|
||||
|
||||
// derive the functions Q and R for the right branch
|
||||
// Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp );
|
||||
// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q );
|
||||
// Cudd_RecursiveDeref( dd, Temp );
|
||||
// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R );
|
||||
|
||||
/*
|
||||
Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars );
|
||||
Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
|
||||
Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars );
|
||||
*/
|
||||
|
||||
// assert( pL->Q != b0 );
|
||||
// assert( pL->R != b0 );
|
||||
// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
|
||||
assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) );
|
||||
assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) );
|
||||
assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) );
|
||||
|
||||
return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs one step of bi-decomposition.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
|
||||
{
|
||||
int CostOr, CostAnd, CostOrL, CostOrR, CostAndL, CostAndR;
|
||||
|
||||
Bdc_IsfClean( p->pIsfOL );
|
||||
Bdc_IsfClean( p->pIsfOR );
|
||||
Bdc_IsfClean( p->pIsfAL );
|
||||
Bdc_IsfClean( p->pIsfAR );
|
||||
|
||||
// perform OR decomposition
|
||||
CostOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR );
|
||||
|
||||
// perform AND decomposition
|
||||
Bdc_IsfNot( pIsf );
|
||||
CostAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR );
|
||||
Bdc_IsfNot( pIsf );
|
||||
Bdc_IsfNot( p->pIsfAL );
|
||||
Bdc_IsfNot( p->pIsfAR );
|
||||
|
||||
// check the hash table
|
||||
Bdc_SuppMinimize( p, p->pIsfOL );
|
||||
CostOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL);
|
||||
Bdc_SuppMinimize( p, p->pIsfOR );
|
||||
CostOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL);
|
||||
Bdc_SuppMinimize( p, p->pIsfAL );
|
||||
CostAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL);
|
||||
Bdc_SuppMinimize( p, p->pIsfAR );
|
||||
CostAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL);
|
||||
|
||||
// check if there is any reuse for the components
|
||||
if ( CostOrL + CostOrR < CostAndL + CostAndR )
|
||||
{
|
||||
Bdc_IsfCopy( pIsfL, p->pIsfOL );
|
||||
Bdc_IsfCopy( pIsfR, p->pIsfOR );
|
||||
return BDC_TYPE_OR;
|
||||
}
|
||||
if ( CostOrL + CostOrR > CostAndL + CostAndR )
|
||||
{
|
||||
Bdc_IsfCopy( pIsfL, p->pIsfAL );
|
||||
Bdc_IsfCopy( pIsfR, p->pIsfAR );
|
||||
return BDC_TYPE_AND;
|
||||
}
|
||||
|
||||
// compare the two-component costs
|
||||
if ( CostOr < CostAnd )
|
||||
{
|
||||
Bdc_IsfCopy( pIsfL, p->pIsfOL );
|
||||
Bdc_IsfCopy( pIsfR, p->pIsfOR );
|
||||
return BDC_TYPE_OR;
|
||||
}
|
||||
return BDC_TYPE_AND;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdcInt.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis [Internal declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 15, 2007.]
|
||||
|
||||
Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __BDC_INT_H__
|
||||
#define __BDC_INT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "kit.h"
|
||||
#include "bdc.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define BDC_SCALE 100 // value used to compute the cost
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// network types
|
||||
typedef enum {
|
||||
BDC_TYPE_NONE = 0, // 0: unknown
|
||||
BDC_TYPE_CONST1, // 1: constant 1
|
||||
BDC_TYPE_PI, // 2: primary input
|
||||
BDC_TYPE_AND, // 4: AND-gate
|
||||
BDC_TYPE_OR, // 5: OR-gate (temporary)
|
||||
BDC_TYPE_XOR, // 6: XOR-gate
|
||||
BDC_TYPE_MUX, // 7: MUX-gate
|
||||
BDC_TYPE_OTHER // 8: unused
|
||||
} Bdc_Type_t;
|
||||
|
||||
typedef struct Bdc_Fun_t_ Bdc_Fun_t;
|
||||
struct Bdc_Fun_t_
|
||||
{
|
||||
int Type; // Const1, PI, AND, XOR, MUX
|
||||
Bdc_Fun_t * pFan0; // fanin of the given node
|
||||
Bdc_Fun_t * pFan1; // fanin of the given node
|
||||
Bdc_Fun_t * pFan2; // fanin of the given node
|
||||
unsigned uSupp; // bit mask of current support
|
||||
unsigned * puFunc; // the function of the node
|
||||
Bdc_Fun_t * pNext; // next function with same support
|
||||
void * pCopy; // the copy field
|
||||
};
|
||||
|
||||
typedef struct Bdc_Isf_t_ Bdc_Isf_t;
|
||||
struct Bdc_Isf_t_
|
||||
{
|
||||
int Var; // the first variable assigned
|
||||
unsigned uSupp; // the current support
|
||||
unsigned * puOn; // on-set
|
||||
unsigned * puOff; // off-set
|
||||
};
|
||||
|
||||
struct Bdc_Man_t_
|
||||
{
|
||||
// external parameters
|
||||
Bdc_Par_t * pPars; // parameter set
|
||||
int nVars; // the number of variables
|
||||
int nWords; // the number of words
|
||||
int nNodesLimit; // the limit on the number of new nodes
|
||||
int nDivsLimit; // the limit on the number of divisors
|
||||
// internal nodes
|
||||
Bdc_Fun_t * pNodes; // storage for decomposition nodes
|
||||
int nNodes; // the number of nodes used
|
||||
int nNodesNew; // the number of nodes used
|
||||
int nNodesAlloc; // the number of nodes allocated
|
||||
Bdc_Fun_t * pRoot; // the root node
|
||||
// resub candidates
|
||||
Bdc_Fun_t ** pTable; // hash table of candidates
|
||||
int nTableSize; // hash table size (1 << nVarsMax)
|
||||
Vec_Int_t * vSpots; // the occupied spots in the table
|
||||
// elementary truth tables
|
||||
Vec_Ptr_t * vTruths; // for const 1 and elementary variables
|
||||
unsigned * puTemp1; // temporary truth table
|
||||
unsigned * puTemp2; // temporary truth table
|
||||
unsigned * puTemp3; // temporary truth table
|
||||
unsigned * puTemp4; // temporary truth table
|
||||
// temporary ISFs
|
||||
Bdc_Isf_t * pIsfOL, IsfOL;
|
||||
Bdc_Isf_t * pIsfOR, IsfOR;
|
||||
Bdc_Isf_t * pIsfAL, IsfAL;
|
||||
Bdc_Isf_t * pIsfAR, IsfAR;
|
||||
// internal memory manager
|
||||
Vec_Int_t * vMemory; // memory for internal truth tables
|
||||
};
|
||||
|
||||
// working with complemented attributes of objects
|
||||
static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((unsigned long)p & (unsigned long)01); }
|
||||
static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p & ~(unsigned long)01); }
|
||||
static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)01); }
|
||||
static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)(c!=0)); }
|
||||
|
||||
static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes == p->nNodesLimit ) return NULL; pRes = p->pNodes + p->nNodes++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); p->nNodesNew++; return pRes; }
|
||||
static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); }
|
||||
static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->Var = 0; }
|
||||
static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; }
|
||||
static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== bdcDec.c ==========================================================*/
|
||||
extern Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
|
||||
/*=== bdcTable.c ==========================================================*/
|
||||
extern Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
|
||||
extern void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc );
|
||||
extern void Bdc_TableClear( Bdc_Man_t * p );
|
||||
extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
|
||||
extern int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdcTable.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis [Hash table for intermediate nodes.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 30, 2007.]
|
||||
|
||||
Revision [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bdcInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Minimizes the support of the ISF.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
|
||||
{
|
||||
int v;
|
||||
// go through the support variables
|
||||
for ( v = 0; v < p->nVars; v++ )
|
||||
{
|
||||
if ( (pIsf->uSupp & (1 << v)) == 0 )
|
||||
continue;
|
||||
Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v );
|
||||
Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v );
|
||||
if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) )
|
||||
continue;
|
||||
// remove the variable
|
||||
Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars );
|
||||
Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars );
|
||||
pIsf->uSupp &= ~(1 << v);
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks containment of the function in the ISF.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth )
|
||||
{
|
||||
return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) &&
|
||||
Kit_TruthIsDisjoint( pIsf->puOff, puTruth, p->nVars );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds the new entry to the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
|
||||
{
|
||||
Bdc_Fun_t * pFunc;
|
||||
for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext )
|
||||
if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) )
|
||||
return pFunc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds the new entry to the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc )
|
||||
{
|
||||
if ( p->pTable[pFunc->uSupp] == NULL )
|
||||
Vec_IntPush( p->vSpots, pFunc->uSupp );
|
||||
pFunc->pNext = p->pTable[pFunc->uSupp];
|
||||
p->pTable[pFunc->uSupp] = pFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds the new entry to the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bdc_TableClear( Bdc_Man_t * p )
|
||||
{
|
||||
int Spot, i;
|
||||
Vec_IntForEachEntry( p->vSpots, Spot, i )
|
||||
p->pTable[Spot] = NULL;
|
||||
Vec_IntClear( p->vSpots );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bdc_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Truth-table-based bi-decomposition engine.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - January 30, 2007.]
|
||||
|
||||
Revision [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bdcInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
SRC += src/aig/bdc/bdcCore.c \
|
||||
src/aig/bdc/bdcDec.c \
|
||||
src/aig/bdc/bdcTable.c
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnf.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnf.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __CNF_H__
|
||||
#define __CNF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "vec.h"
|
||||
#include "aig.h"
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Cnf_Man_t_ Cnf_Man_t;
|
||||
typedef struct Cnf_Dat_t_ Cnf_Dat_t;
|
||||
typedef struct Cnf_Cut_t_ Cnf_Cut_t;
|
||||
|
||||
// the CNF asserting outputs of AIG to be 1
|
||||
struct Cnf_Dat_t_
|
||||
{
|
||||
Aig_Man_t * pMan; // the AIG manager, for which CNF is computed
|
||||
int nVars; // the number of variables
|
||||
int nLiterals; // the number of CNF literals
|
||||
int nClauses; // the number of CNF clauses
|
||||
int ** pClauses; // the CNF clauses
|
||||
int * pVarNums; // the number of CNF variable for each node ID (-1 if unused)
|
||||
};
|
||||
|
||||
// the cut used to represent node in the AIG
|
||||
struct Cnf_Cut_t_
|
||||
{
|
||||
char nFanins; // the number of leaves
|
||||
char Cost; // the cost of this cut
|
||||
short nWords; // the number of words in truth table
|
||||
Vec_Int_t * vIsop[2]; // neg/pos ISOPs
|
||||
int pFanins[0]; // the fanins (followed by the truth table)
|
||||
};
|
||||
|
||||
// the CNF computation manager
|
||||
struct Cnf_Man_t_
|
||||
{
|
||||
Aig_Man_t * pManAig; // the underlying AIG manager
|
||||
char * pSopSizes; // sizes of SOPs for 4-variable functions
|
||||
char ** pSops; // the SOPs for 4-variable functions
|
||||
int aArea; // the area of the mapping
|
||||
Aig_MmFlex_t * pMemCuts; // memory manager for cuts
|
||||
int nMergeLimit; // the limit on the size of merged cut
|
||||
unsigned * pTruths[4]; // temporary truth tables
|
||||
Vec_Int_t * vMemory; // memory for intermediate ISOP representation
|
||||
int timeCuts;
|
||||
int timeMap;
|
||||
int timeSave;
|
||||
};
|
||||
|
||||
|
||||
static inline Dar_Cut_t * Dar_ObjBestCut( Aig_Obj_t * pObj ) { Dar_Cut_t * pCut; int i; Dar_ObjForEachCut( pObj, pCut, i ) if ( pCut->fBest ) return pCut; return NULL; }
|
||||
|
||||
static inline int Cnf_CutSopCost( Cnf_Man_t * p, Dar_Cut_t * pCut ) { return p->pSopSizes[pCut->uTruth] + p->pSopSizes[0xFFFF & ~pCut->uTruth]; }
|
||||
|
||||
static inline int Cnf_CutLeaveNum( Cnf_Cut_t * pCut ) { return pCut->nFanins; }
|
||||
static inline int * Cnf_CutLeaves( Cnf_Cut_t * pCut ) { return pCut->pFanins; }
|
||||
static inline unsigned * Cnf_CutTruth( Cnf_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nFanins); }
|
||||
|
||||
static inline Cnf_Cut_t * Cnf_ObjBestCut( Aig_Obj_t * pObj ) { return pObj->pData; }
|
||||
static inline void Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut ) { pObj->pData = pCut; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// iterator over leaves of the cut
|
||||
#define Cnf_CutForEachLeaf( p, pCut, pLeaf, i ) \
|
||||
for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== cnfCore.c ========================================================*/
|
||||
extern Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs );
|
||||
extern Cnf_Man_t * Cnf_ManRead();
|
||||
extern void Cnf_ClearMemory();
|
||||
/*=== cnfCut.c ========================================================*/
|
||||
extern Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern void Cnf_CutPrint( Cnf_Cut_t * pCut );
|
||||
extern void Cnf_CutFree( Cnf_Cut_t * pCut );
|
||||
extern void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes );
|
||||
extern Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan );
|
||||
/*=== cnfData.c ========================================================*/
|
||||
extern void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops );
|
||||
/*=== cnfMan.c ========================================================*/
|
||||
extern Cnf_Man_t * Cnf_ManStart();
|
||||
extern void Cnf_ManStop( Cnf_Man_t * p );
|
||||
extern Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p );
|
||||
extern void Cnf_DataFree( Cnf_Dat_t * p );
|
||||
extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable );
|
||||
void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p );
|
||||
/*=== cnfMap.c ========================================================*/
|
||||
extern void Cnf_DeriveMapping( Cnf_Man_t * p );
|
||||
extern int Cnf_ManMapForCnf( Cnf_Man_t * p );
|
||||
/*=== cnfPost.c ========================================================*/
|
||||
extern void Cnf_ManTransferCuts( Cnf_Man_t * p );
|
||||
extern void Cnf_ManFreeCuts( Cnf_Man_t * p );
|
||||
extern void Cnf_ManPostprocess( Cnf_Man_t * p );
|
||||
/*=== cnfUtil.c ========================================================*/
|
||||
extern Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect );
|
||||
extern Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder );
|
||||
/*=== cnfWrite.c ========================================================*/
|
||||
extern void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover );
|
||||
extern Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs );
|
||||
extern Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Cnf_Man_t * s_pManCnf = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts AIG into the SAT solver.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs )
|
||||
{
|
||||
Cnf_Man_t * p;
|
||||
Cnf_Dat_t * pCnf;
|
||||
Vec_Ptr_t * vMapped;
|
||||
Aig_MmFixed_t * pMemCuts;
|
||||
int clk;
|
||||
// allocate the CNF manager
|
||||
if ( s_pManCnf == NULL )
|
||||
s_pManCnf = Cnf_ManStart();
|
||||
// connect the managers
|
||||
p = s_pManCnf;
|
||||
p->pManAig = pAig;
|
||||
|
||||
// generate cuts for all nodes, assign cost, and find best cuts
|
||||
clk = clock();
|
||||
pMemCuts = Dar_ManComputeCuts( pAig, 10 );
|
||||
p->timeCuts = clock() - clk;
|
||||
|
||||
// find the mapping
|
||||
clk = clock();
|
||||
Cnf_DeriveMapping( p );
|
||||
p->timeMap = clock() - clk;
|
||||
// Aig_ManScanMapping( p, 1 );
|
||||
|
||||
// convert it into CNF
|
||||
clk = clock();
|
||||
Cnf_ManTransferCuts( p );
|
||||
vMapped = Cnf_ManScanMapping( p, 1, 1 );
|
||||
pCnf = Cnf_ManWriteCnf( p, vMapped, nOutputs );
|
||||
Vec_PtrFree( vMapped );
|
||||
Aig_MmFixedStop( pMemCuts, 0 );
|
||||
p->timeSave = clock() - clk;
|
||||
|
||||
// reset reference counters
|
||||
Aig_ManResetRefs( pAig );
|
||||
//PRT( "Cuts ", p->timeCuts );
|
||||
//PRT( "Map ", p->timeMap );
|
||||
//PRT( "Saving ", p->timeSave );
|
||||
return pCnf;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Man_t * Cnf_ManRead()
|
||||
{
|
||||
return s_pManCnf;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ClearMemory()
|
||||
{
|
||||
if ( s_pManCnf == NULL )
|
||||
return;
|
||||
Cnf_ManStop( s_pManCnf );
|
||||
s_pManCnf = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Dat_t * Cnf_Derive_old( Aig_Man_t * pAig )
|
||||
{
|
||||
/*
|
||||
// iteratively improve area flow
|
||||
for ( i = 0; i < nIters; i++ )
|
||||
{
|
||||
clk = clock();
|
||||
Cnf_ManScanMapping( p, 0 );
|
||||
Cnf_ManMapForCnf( p );
|
||||
PRT( "iter ", clock() - clk );
|
||||
}
|
||||
*/
|
||||
// write the file
|
||||
vMapped = Aig_ManScanMapping( p, 1 );
|
||||
Vec_PtrFree( vMapped );
|
||||
|
||||
clk = clock();
|
||||
Cnf_ManTransferCuts( p );
|
||||
|
||||
Cnf_ManPostprocess( p );
|
||||
Cnf_ManScanMapping( p, 0 );
|
||||
/*
|
||||
Cnf_ManPostprocess( p );
|
||||
Cnf_ManScanMapping( p, 0 );
|
||||
Cnf_ManPostprocess( p );
|
||||
Cnf_ManScanMapping( p, 0 );
|
||||
*/
|
||||
PRT( "Ext ", clock() - clk );
|
||||
|
||||
/*
|
||||
vMapped = Cnf_ManScanMapping( p, 1 );
|
||||
pCnf = Cnf_ManWriteCnf( p, vMapped );
|
||||
Vec_PtrFree( vMapped );
|
||||
|
||||
// clean up
|
||||
Cnf_ManFreeCuts( p );
|
||||
Dar_ManCutsFree( pAig );
|
||||
return pCnf;
|
||||
*/
|
||||
Aig_MmFixedStop( pMemCuts, 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfCut.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
#include "kit.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates cut of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves )
|
||||
{
|
||||
Cnf_Cut_t * pCut;
|
||||
int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Aig_TruthWordNum(nLeaves);
|
||||
pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize );
|
||||
pCut->nFanins = nLeaves;
|
||||
pCut->nWords = Aig_TruthWordNum(nLeaves);
|
||||
pCut->vIsop[0] = pCut->vIsop[1] = NULL;
|
||||
return pCut;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deallocates cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutFree( Cnf_Cut_t * pCut )
|
||||
{
|
||||
if ( pCut->vIsop[0] )
|
||||
Vec_IntFree( pCut->vIsop[0] );
|
||||
if ( pCut->vIsop[1] )
|
||||
Vec_IntFree( pCut->vIsop[1] );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates cut for the given node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Dar_Cut_t * pCutBest;
|
||||
Cnf_Cut_t * pCut;
|
||||
unsigned * pTruth;
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
pCutBest = Dar_ObjBestCut( pObj );
|
||||
assert( pCutBest != NULL );
|
||||
assert( pCutBest->nLeaves <= 4 );
|
||||
pCut = Cnf_CutAlloc( p, pCutBest->nLeaves );
|
||||
memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves );
|
||||
pTruth = Cnf_CutTruth(pCut);
|
||||
*pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth;
|
||||
pCut->Cost = Cnf_CutSopCost( p, pCutBest );
|
||||
return pCut;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deallocates cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutPrint( Cnf_Cut_t * pCut )
|
||||
{
|
||||
int i;
|
||||
printf( "{" );
|
||||
for ( i = 0; i < pCut->nFanins; i++ )
|
||||
printf( "%d ", pCut->pFanins[i] );
|
||||
printf( " } " );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates cut of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
|
||||
{
|
||||
assert( pObj->nRefs > 0 );
|
||||
pObj->nRefs--;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates cut of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
|
||||
{
|
||||
pObj->nRefs++;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Allocates cut of the given size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes )
|
||||
{
|
||||
Cnf_CutDeref( p, pCut );
|
||||
Cnf_CutDeref( p, pCutFan );
|
||||
Cnf_CutRef( p, pCutRes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two arrays of integers.]
|
||||
|
||||
Description [Returns the number of items.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins )
|
||||
{
|
||||
int i, k, nFanins = 0;
|
||||
for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; )
|
||||
{
|
||||
if ( pCut->pFanins[i] == pCutFan->pFanins[k] )
|
||||
pFanins[nFanins++] = pCut->pFanins[i], i++, k++;
|
||||
else if ( pCut->pFanins[i] < pCutFan->pFanins[k] )
|
||||
pFanins[nFanins++] = pCut->pFanins[i], i++;
|
||||
else
|
||||
pFanins[nFanins++] = pCutFan->pFanins[k], k++;
|
||||
}
|
||||
for ( ; i < pCut->nFanins; i++ )
|
||||
pFanins[nFanins++] = pCut->pFanins[i];
|
||||
for ( ; k < pCutFan->nFanins; k++ )
|
||||
pFanins[nFanins++] = pCutFan->pFanins[k];
|
||||
return nFanins;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 )
|
||||
{
|
||||
unsigned uPhase = 0;
|
||||
int i, k;
|
||||
for ( i = k = 0; i < pCut->nFanins; i++ )
|
||||
{
|
||||
if ( k == pCut1->nFanins )
|
||||
break;
|
||||
if ( pCut->pFanins[i] < pCut1->pFanins[k] )
|
||||
continue;
|
||||
assert( pCut->pFanins[i] == pCut1->pFanins[k] );
|
||||
uPhase |= (1 << i);
|
||||
k++;
|
||||
}
|
||||
return uPhase;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Removes the fanin variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
|
||||
{
|
||||
int i;
|
||||
assert( pCut->pFanins[iVar] == iFan );
|
||||
pCut->nFanins--;
|
||||
for ( i = iVar; i < pCut->nFanins; i++ )
|
||||
pCut->pFanins[i] = pCut->pFanins[i+1];
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Inserts the fanin variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
|
||||
{
|
||||
int i;
|
||||
for ( i = pCut->nFanins; i > iVar; i-- )
|
||||
pCut->pFanins[i] = pCut->pFanins[i-1];
|
||||
pCut->pFanins[iVar] = iFan;
|
||||
pCut->nFanins++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description [Returns NULL of the cuts cannot be merged.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan )
|
||||
{
|
||||
Cnf_Cut_t * pCutRes;
|
||||
static int pFanins[32];
|
||||
unsigned * pTruth, * pTruthFan, * pTruthRes;
|
||||
unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3];
|
||||
unsigned uPhase, uPhaseFan;
|
||||
int i, iVar, nFanins, RetValue;
|
||||
|
||||
// make sure the second cut is the fanin of the first
|
||||
for ( iVar = 0; iVar < pCut->nFanins; iVar++ )
|
||||
if ( pCut->pFanins[iVar] == iFan )
|
||||
break;
|
||||
assert( iVar < pCut->nFanins );
|
||||
// remove this variable
|
||||
Cnf_CutRemoveIthVar( pCut, iVar, iFan );
|
||||
// merge leaves of the cuts
|
||||
nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins );
|
||||
if ( nFanins+1 > p->nMergeLimit )
|
||||
{
|
||||
Cnf_CutInsertIthVar( pCut, iVar, iFan );
|
||||
return NULL;
|
||||
}
|
||||
// create new cut
|
||||
pCutRes = Cnf_CutAlloc( p, nFanins );
|
||||
memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins );
|
||||
assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins );
|
||||
|
||||
// derive its truth table
|
||||
// get the truth tables in the composition space
|
||||
pTruth = Cnf_CutTruth(pCut);
|
||||
pTruthFan = Cnf_CutTruth(pCutFan);
|
||||
pTruthRes = Cnf_CutTruth(pCutRes);
|
||||
for ( i = 0; i < 2*pCutRes->nWords; i++ )
|
||||
pTop[i] = pTruth[i % pCut->nWords];
|
||||
for ( i = 0; i < pCutRes->nWords; i++ )
|
||||
pFan[i] = pTruthFan[i % pCutFan->nWords];
|
||||
// move the variable to the end
|
||||
uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar);
|
||||
Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 );
|
||||
// compute the phases
|
||||
uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins);
|
||||
uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan );
|
||||
// permute truth-tables to the common support
|
||||
Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 );
|
||||
Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 );
|
||||
// perform Boolean operation
|
||||
Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins );
|
||||
// return the cut to its original condition
|
||||
Cnf_CutInsertIthVar( pCut, iVar, iFan );
|
||||
// consider the simple case
|
||||
if ( pCutRes->nFanins < 5 )
|
||||
{
|
||||
pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes];
|
||||
return pCutRes;
|
||||
}
|
||||
|
||||
// derive ISOP for positive phase
|
||||
RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
|
||||
pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
|
||||
// derive ISOP for negative phase
|
||||
Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
|
||||
RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
|
||||
pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
|
||||
Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
|
||||
|
||||
// compute the cut cost
|
||||
if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL )
|
||||
pCutRes->Cost = 127;
|
||||
else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 )
|
||||
pCutRes->Cost = 127;
|
||||
else
|
||||
pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]);
|
||||
return pCutRes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,202 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
#include "satSolver.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline int Cnf_Lit2Var( int Lit ) { return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1; }
|
||||
static inline int Cnf_Lit2Var2( int Lit ) { return (Lit & 1)? -(Lit >> 1) : (Lit >> 1); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the fraiging manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Man_t * Cnf_ManStart()
|
||||
{
|
||||
Cnf_Man_t * p;
|
||||
int i;
|
||||
// allocate the manager
|
||||
p = ALLOC( Cnf_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Cnf_Man_t) );
|
||||
// derive internal data structures
|
||||
Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
|
||||
// allocate memory manager for cuts
|
||||
p->pMemCuts = Aig_MmFlexStart();
|
||||
p->nMergeLimit = 10;
|
||||
// allocate temporary truth tables
|
||||
p->pTruths[0] = ALLOC( unsigned, 4 * Aig_TruthWordNum(p->nMergeLimit) );
|
||||
for ( i = 1; i < 4; i++ )
|
||||
p->pTruths[i] = p->pTruths[i-1] + Aig_TruthWordNum(p->nMergeLimit);
|
||||
p->vMemory = Vec_IntAlloc( 1 << 18 );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the fraiging manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ManStop( Cnf_Man_t * p )
|
||||
{
|
||||
Vec_IntFree( p->vMemory );
|
||||
free( p->pTruths[0] );
|
||||
Aig_MmFlexStop( p->pMemCuts, 0 );
|
||||
free( p->pSopSizes );
|
||||
free( p->pSops[1] );
|
||||
free( p->pSops );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the array of CI IDs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p )
|
||||
{
|
||||
Vec_Int_t * vCiIds;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
vCiIds = Vec_IntAlloc( Aig_ManPiNum(p) );
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] );
|
||||
return vCiIds;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_DataFree( Cnf_Dat_t * p )
|
||||
{
|
||||
if ( p == NULL )
|
||||
return;
|
||||
free( p->pClauses[0] );
|
||||
free( p->pClauses );
|
||||
free( p->pVarNums );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes CNF into a file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable )
|
||||
{
|
||||
FILE * pFile;
|
||||
int * pLit, * pStop, i;
|
||||
pFile = fopen( pFileName, "w" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" );
|
||||
fprintf( pFile, "p %d %d\n", p->nVars, p->nClauses );
|
||||
for ( i = 0; i < p->nClauses; i++ )
|
||||
{
|
||||
for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ )
|
||||
fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) );
|
||||
fprintf( pFile, "0\n" );
|
||||
}
|
||||
fprintf( pFile, "\n" );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes CNF into a file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p )
|
||||
{
|
||||
sat_solver * pSat;
|
||||
int i, status;
|
||||
pSat = sat_solver_new();
|
||||
sat_solver_setnvars( pSat, p->nVars );
|
||||
for ( i = 0; i < p->nClauses; i++ )
|
||||
{
|
||||
if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) )
|
||||
{
|
||||
sat_solver_delete( pSat );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
status = sat_solver_simplify(pSat);
|
||||
if ( status == 0 )
|
||||
{
|
||||
sat_solver_delete( pSat );
|
||||
return NULL;
|
||||
}
|
||||
return pSat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfMap.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutAssignAreaFlow( Cnf_Man_t * p, Dar_Cut_t * pCut, int * pAreaFlows )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i;
|
||||
pCut->Value = 0;
|
||||
pCut->uSign = 100 * Cnf_CutSopCost( p, pCut );
|
||||
Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i )
|
||||
{
|
||||
pCut->Value += pLeaf->nRefs;
|
||||
if ( !Aig_ObjIsNode(pLeaf) )
|
||||
continue;
|
||||
assert( pLeaf->nRefs > 0 );
|
||||
pCut->uSign += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow of the supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_CutSuperAreaFlow( Vec_Ptr_t * vSuper, int * pAreaFlows )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i, nAreaFlow;
|
||||
nAreaFlow = 100 * (Vec_PtrSize(vSuper) + 1);
|
||||
Vec_PtrForEachEntry( vSuper, pLeaf, i )
|
||||
{
|
||||
pLeaf = Aig_Regular(pLeaf);
|
||||
if ( !Aig_ObjIsNode(pLeaf) )
|
||||
continue;
|
||||
assert( pLeaf->nRefs > 0 );
|
||||
nAreaFlow += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1);
|
||||
}
|
||||
return nAreaFlow;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_DeriveMapping( Cnf_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vSuper;
|
||||
Aig_Obj_t * pObj;
|
||||
Dar_Cut_t * pCut, * pCutBest;
|
||||
int i, k, AreaFlow, * pAreaFlows;
|
||||
// allocate area flows
|
||||
pAreaFlows = ALLOC( int, Aig_ManObjIdMax(p->pManAig) + 1 );
|
||||
memset( pAreaFlows, 0, sizeof(int) * (Aig_ManObjIdMax(p->pManAig) + 1) );
|
||||
// visit the nodes in the topological order and update their best cuts
|
||||
vSuper = Vec_PtrAlloc( 100 );
|
||||
Aig_ManForEachNode( p->pManAig, pObj, i )
|
||||
{
|
||||
// go through the cuts
|
||||
pCutBest = NULL;
|
||||
Dar_ObjForEachCut( pObj, pCut, k )
|
||||
{
|
||||
pCut->fBest = 0;
|
||||
if ( k == 0 )
|
||||
continue;
|
||||
Cnf_CutAssignAreaFlow( p, pCut, pAreaFlows );
|
||||
if ( pCutBest == NULL || pCutBest->uSign > pCut->uSign ||
|
||||
(pCutBest->uSign == pCut->uSign && pCutBest->Value < pCut->Value) )
|
||||
pCutBest = pCut;
|
||||
}
|
||||
// check the big cut
|
||||
// Aig_ObjCollectSuper( pObj, vSuper );
|
||||
// get the area flow of this cut
|
||||
// AreaFlow = Cnf_CutSuperAreaFlow( vSuper, pAreaFlows );
|
||||
AreaFlow = AIG_INFINITY;
|
||||
if ( AreaFlow >= (int)pCutBest->uSign )
|
||||
{
|
||||
pAreaFlows[pObj->Id] = pCutBest->uSign;
|
||||
pCutBest->fBest = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAreaFlows[pObj->Id] = AreaFlow;
|
||||
pObj->fMarkB = 1; // mark the special node
|
||||
}
|
||||
}
|
||||
Vec_PtrFree( vSuper );
|
||||
free( pAreaFlows );
|
||||
|
||||
/*
|
||||
// compute the area of mapping
|
||||
AreaFlow = 0;
|
||||
Aig_ManForEachPo( p->pManAig, pObj, i )
|
||||
AreaFlow += Dar_ObjBestCut(Aig_ObjFanin0(pObj))->uSign / 100 / Aig_ObjFanin0(pObj)->nRefs;
|
||||
printf( "Area of the network = %d.\n", AreaFlow );
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_CutDeref( Aig_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i;
|
||||
Dar_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs > 0 );
|
||||
if ( --pLeaf->nRefs > 0 || !Aig_ObjIsAnd(pLeaf) )
|
||||
continue;
|
||||
Aig_CutDeref( p, Aig_ObjBestCut(pLeaf) );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_CutRef( Aig_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i, Area = pCut->Value;
|
||||
Dar_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs >= 0 );
|
||||
if ( pLeaf->nRefs++ > 0 || !Aig_ObjIsAnd(pLeaf) )
|
||||
continue;
|
||||
Area += Aig_CutRef( p, Aig_ObjBestCut(pLeaf) );
|
||||
}
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes exact area of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_CutArea( Aig_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
int Area;
|
||||
Area = Aig_CutRef( p, pCut );
|
||||
Aig_CutDeref( p, pCut );
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the second cut is better.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Cnf_CutCompare( Dar_Cut_t * pC0, Dar_Cut_t * pC1 )
|
||||
{
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 ) // smaller area flow is better
|
||||
return 1;
|
||||
// if ( pC0->NoRefs < pC1->NoRefs )
|
||||
// return -1;
|
||||
// if ( pC0->NoRefs > pC1->NoRefs ) // fewer non-referenced fanins is better
|
||||
// return 1;
|
||||
// if ( pC0->FanRefs / pC0->nLeaves > pC1->FanRefs / pC1->nLeaves )
|
||||
// return -1;
|
||||
// if ( pC0->FanRefs / pC0->nLeaves < pC1->FanRefs / pC1->nLeaves )
|
||||
// return 1; // larger average fanin ref-counter is better
|
||||
// return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the cut with the smallest area flow.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Cut_t * Cnf_ObjFindBestCut( Aig_Obj_t * pObj )
|
||||
{
|
||||
Dar_Cut_t * pCut, * pCutBest;
|
||||
int i;
|
||||
pCutBest = NULL;
|
||||
Dar_ObjForEachCut( pObj, pCut, i )
|
||||
if ( pCutBest == NULL || Cnf_CutCompare(pCutBest, pCut) == 1 )
|
||||
pCutBest = pCut;
|
||||
return pCutBest;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_CutAssignArea( Cnf_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i;
|
||||
pCut->Area = (float)pCut->Cost;
|
||||
pCut->NoRefs = 0;
|
||||
pCut->FanRefs = 0;
|
||||
Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pLeaf) )
|
||||
continue;
|
||||
if ( pLeaf->nRefs == 0 )
|
||||
{
|
||||
pCut->Area += Aig_ObjBestCut(pLeaf)->Cost;
|
||||
pCut->NoRefs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pCut->FanRefs + pLeaf->nRefs > 15 )
|
||||
pCut->FanRefs = 15;
|
||||
else
|
||||
pCut->FanRefs += pLeaf->nRefs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs one round of "area recovery" using exact local area.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_ManMapForCnf( Cnf_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
Dar_Cut_t * pCut, * pCutBest;
|
||||
int i, k;
|
||||
// visit the nodes in the topological order and update their best cuts
|
||||
Aig_ManForEachNode( p->pManAig, pObj, i )
|
||||
{
|
||||
// find the old best cut
|
||||
pCutBest = Aig_ObjBestCut(pObj);
|
||||
Dar_ObjClearBestCut(pCutBest);
|
||||
// if the node is used, dereference its cut
|
||||
if ( pObj->nRefs )
|
||||
Aig_CutDeref( p->pManAig, pCutBest );
|
||||
|
||||
// evaluate the cuts of this node
|
||||
Dar_ObjForEachCut( pObj, pCut, k )
|
||||
// Cnf_CutAssignAreaFlow( p, pCut );
|
||||
pCut->Area = (float)Cnf_CutArea( p->pManAig, pCut );
|
||||
|
||||
// find the new best cut
|
||||
pCutBest = Cnf_ObjFindBestCut(pObj);
|
||||
Dar_ObjSetBestCut( pCutBest );
|
||||
// if the node is used, reference its cut
|
||||
if ( pObj->nRefs )
|
||||
Aig_CutRef( p->pManAig, pCutBest );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfPost.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfPost.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ManPostprocess_old( Cnf_Man_t * p )
|
||||
{
|
||||
// extern int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCutR, Dar_Cut_t * pCutL, int Leaf );
|
||||
int nNew, Gain, nGain = 0, nVars = 0;
|
||||
|
||||
Aig_Obj_t * pObj, * pFan;
|
||||
Dar_Cut_t * pCutBest, * pCut;
|
||||
int i, k;//, a, b, Counter;
|
||||
Aig_ManForEachObj( p->pManAig, pObj, i )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
continue;
|
||||
if ( pObj->nRefs == 0 )
|
||||
continue;
|
||||
// pCutBest = Aig_ObjBestCut(pObj);
|
||||
pCutBest = NULL;
|
||||
|
||||
Dar_CutForEachLeaf( p->pManAig, pCutBest, pFan, k )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pFan) )
|
||||
continue;
|
||||
assert( pFan->nRefs != 0 );
|
||||
if ( pFan->nRefs != 1 )
|
||||
continue;
|
||||
// pCut = Aig_ObjBestCut(pFan);
|
||||
pCut = NULL;
|
||||
/*
|
||||
// find how many common variable they have
|
||||
Counter = 0;
|
||||
for ( a = 0; a < (int)pCut->nLeaves; a++ )
|
||||
{
|
||||
for ( b = 0; b < (int)pCutBest->nLeaves; b++ )
|
||||
if ( pCut->pLeaves[a] == pCutBest->pLeaves[b] )
|
||||
break;
|
||||
if ( b == (int)pCutBest->nLeaves )
|
||||
continue;
|
||||
Counter++;
|
||||
}
|
||||
printf( "%d ", Counter );
|
||||
*/
|
||||
// find the new truth table after collapsing these two cuts
|
||||
|
||||
|
||||
// nNew = Aig_ManLargeCutEval( p->pManAig, pObj, pCutBest, pCut, pFan->Id );
|
||||
nNew = 0;
|
||||
|
||||
|
||||
// printf( "%d+%d=%d:%d(%d) ", pCutBest->Cost, pCut->Cost,
|
||||
// pCutBest->Cost+pCut->Cost, nNew, pCutBest->Cost+pCut->Cost-nNew );
|
||||
|
||||
Gain = pCutBest->Value + pCut->Value - nNew;
|
||||
if ( Gain > 0 )
|
||||
{
|
||||
nGain += Gain;
|
||||
nVars++;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf( "Total gain = %d. Vars = %d.\n", nGain, nVars );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transfers cuts of the mapped nodes into internal representation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ManTransferCuts( Cnf_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_MmFlexRestart( p->pMemCuts );
|
||||
Aig_ManForEachObj( p->pManAig, pObj, i )
|
||||
{
|
||||
if ( Aig_ObjIsNode(pObj) && pObj->nRefs > 0 )
|
||||
pObj->pData = Cnf_CutCreate( p, pObj );
|
||||
else
|
||||
pObj->pData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transfers cuts of the mapped nodes into internal representation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ManFreeCuts( Cnf_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManForEachObj( p->pManAig, pObj, i )
|
||||
if ( pObj->pData )
|
||||
{
|
||||
Cnf_CutFree( pObj->pData );
|
||||
pObj->pData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_ManPostprocess( Cnf_Man_t * p )
|
||||
{
|
||||
Cnf_Cut_t * pCut, * pCutFan, * pCutRes;
|
||||
Aig_Obj_t * pObj, * pFan;
|
||||
int Order[16], Costs[16];
|
||||
int i, k, fChanges;
|
||||
Aig_ManForEachNode( p->pManAig, pObj, i )
|
||||
{
|
||||
if ( pObj->nRefs == 0 )
|
||||
continue;
|
||||
pCut = Cnf_ObjBestCut(pObj);
|
||||
|
||||
// sort fanins according to their size
|
||||
Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k )
|
||||
{
|
||||
Order[k] = k;
|
||||
Costs[k] = Aig_ObjIsNode(pFan)? Cnf_ObjBestCut(pFan)->Cost : 0;
|
||||
}
|
||||
// sort the cuts by Weight
|
||||
do {
|
||||
int Temp;
|
||||
fChanges = 0;
|
||||
for ( k = 0; k < pCut->nFanins - 1; k++ )
|
||||
{
|
||||
if ( Costs[Order[k]] <= Costs[Order[k+1]] )
|
||||
continue;
|
||||
Temp = Order[k];
|
||||
Order[k] = Order[k+1];
|
||||
Order[k+1] = Temp;
|
||||
fChanges = 1;
|
||||
}
|
||||
} while ( fChanges );
|
||||
|
||||
|
||||
// Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k )
|
||||
for ( k = 0; (k < (int)(pCut)->nFanins) && ((pFan) = Aig_ManObj(p->pManAig, (pCut)->pFanins[Order[k]])); k++ )
|
||||
{
|
||||
if ( !Aig_ObjIsNode(pFan) )
|
||||
continue;
|
||||
assert( pFan->nRefs != 0 );
|
||||
if ( pFan->nRefs != 1 )
|
||||
continue;
|
||||
pCutFan = Cnf_ObjBestCut(pFan);
|
||||
// try composing these two cuts
|
||||
// Cnf_CutPrint( pCut );
|
||||
pCutRes = Cnf_CutCompose( p, pCut, pCutFan, pFan->Id );
|
||||
// Cnf_CutPrint( pCut );
|
||||
// printf( "\n" );
|
||||
// check if the cost if reduced
|
||||
if ( pCutRes == NULL || pCutRes->Cost == 127 || pCutRes->Cost > pCut->Cost + pCutFan->Cost )
|
||||
{
|
||||
if ( pCutRes )
|
||||
Cnf_CutFree( pCutRes );
|
||||
continue;
|
||||
}
|
||||
// update the cut
|
||||
Cnf_ObjSetBestCut( pObj, pCutRes );
|
||||
Cnf_ObjSetBestCut( pFan, NULL );
|
||||
Cnf_CutUpdateRefs( p, pCut, pCutFan, pCutRes );
|
||||
assert( pFan->nRefs == 0 );
|
||||
Cnf_CutFree( pCut );
|
||||
Cnf_CutFree( pCutFan );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfUtil.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
Dar_Cut_t * pCutBest;
|
||||
int aArea, i;
|
||||
if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
|
||||
return 0;
|
||||
assert( Aig_ObjIsAnd(pObj) );
|
||||
// collect the node first to derive pre-order
|
||||
if ( vMapped )
|
||||
Vec_PtrPush( vMapped, pObj );
|
||||
// visit the transitive fanin of the selected cut
|
||||
if ( pObj->fMarkB )
|
||||
{
|
||||
Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 );
|
||||
Aig_ObjCollectSuper( pObj, vSuper );
|
||||
aArea = Vec_PtrSize(vSuper) + 1;
|
||||
Vec_PtrForEachEntry( vSuper, pLeaf, i )
|
||||
aArea += Aig_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped );
|
||||
Vec_PtrFree( vSuper );
|
||||
////////////////////////////
|
||||
pObj->fMarkB = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCutBest = Dar_ObjBestCut( pObj );
|
||||
aArea = Cnf_CutSopCost( p, pCutBest );
|
||||
Dar_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i )
|
||||
aArea += Aig_ManScanMapping_rec( p, pLeaf, vMapped );
|
||||
}
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description [Collects the nodes in reverse topological order.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect )
|
||||
{
|
||||
Vec_Ptr_t * vMapped = NULL;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// clean all references
|
||||
Aig_ManForEachObj( p->pManAig, pObj, i )
|
||||
pObj->nRefs = 0;
|
||||
// allocate the array
|
||||
if ( fCollect )
|
||||
vMapped = Vec_PtrAlloc( 1000 );
|
||||
// collect nodes reachable from POs in the DFS order through the best cuts
|
||||
p->aArea = 0;
|
||||
Aig_ManForEachPo( p->pManAig, pObj, i )
|
||||
p->aArea += Aig_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped );
|
||||
// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 );
|
||||
return vMapped;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped, int fPreorder )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
Cnf_Cut_t * pCutBest;
|
||||
int aArea, i;
|
||||
if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
|
||||
return 0;
|
||||
assert( Aig_ObjIsAnd(pObj) );
|
||||
assert( pObj->pData != NULL );
|
||||
// add the node to the mapping
|
||||
if ( vMapped && fPreorder )
|
||||
Vec_PtrPush( vMapped, pObj );
|
||||
// visit the transitive fanin of the selected cut
|
||||
if ( pObj->fMarkB )
|
||||
{
|
||||
Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 );
|
||||
Aig_ObjCollectSuper( pObj, vSuper );
|
||||
aArea = Vec_PtrSize(vSuper) + 1;
|
||||
Vec_PtrForEachEntry( vSuper, pLeaf, i )
|
||||
aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder );
|
||||
Vec_PtrFree( vSuper );
|
||||
////////////////////////////
|
||||
pObj->fMarkB = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCutBest = pObj->pData;
|
||||
assert( pCutBest->Cost < 127 );
|
||||
aArea = pCutBest->Cost;
|
||||
Cnf_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i )
|
||||
aArea += Cnf_ManScanMapping_rec( p, pLeaf, vMapped, fPreorder );
|
||||
}
|
||||
// add the node to the mapping
|
||||
if ( vMapped && !fPreorder )
|
||||
Vec_PtrPush( vMapped, pObj );
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description [Collects the nodes in reverse topological order.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder )
|
||||
{
|
||||
Vec_Ptr_t * vMapped = NULL;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
// clean all references
|
||||
Aig_ManForEachObj( p->pManAig, pObj, i )
|
||||
pObj->nRefs = 0;
|
||||
// allocate the array
|
||||
if ( fCollect )
|
||||
vMapped = Vec_PtrAlloc( 1000 );
|
||||
// collect nodes reachable from POs in the DFS order through the best cuts
|
||||
p->aArea = 0;
|
||||
Aig_ManForEachPo( p->pManAig, pObj, i )
|
||||
p->aArea += Cnf_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped, fPreorder );
|
||||
// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 );
|
||||
return vMapped;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnfWrite.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnfWrite.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes the cover into the array.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover )
|
||||
{
|
||||
int Lits[4], Cube, iCube, i, b;
|
||||
Vec_IntClear( vCover );
|
||||
for ( i = 0; i < nCubes; i++ )
|
||||
{
|
||||
Cube = pSop[i];
|
||||
for ( b = 0; b < 4; b++ )
|
||||
{
|
||||
if ( Cube % 3 == 0 )
|
||||
Lits[b] = 1;
|
||||
else if ( Cube % 3 == 1 )
|
||||
Lits[b] = 2;
|
||||
else
|
||||
Lits[b] = 0;
|
||||
Cube = Cube / 3;
|
||||
}
|
||||
iCube = 0;
|
||||
for ( b = 0; b < 4; b++ )
|
||||
iCube = (iCube << 2) | Lits[b];
|
||||
Vec_IntPush( vCover, iCube );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of literals in the SOP.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_SopCountLiterals( char * pSop, int nCubes )
|
||||
{
|
||||
int nLits = 0, Cube, i, b;
|
||||
for ( i = 0; i < nCubes; i++ )
|
||||
{
|
||||
Cube = pSop[i];
|
||||
for ( b = 0; b < 4; b++ )
|
||||
{
|
||||
if ( Cube % 3 != 2 )
|
||||
nLits++;
|
||||
Cube = Cube / 3;
|
||||
}
|
||||
}
|
||||
return nLits;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of literals in the SOP.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_IsopCountLiterals( Vec_Int_t * vIsop, int nVars )
|
||||
{
|
||||
int nLits = 0, Cube, i, b;
|
||||
Vec_IntForEachEntry( vIsop, Cube, i )
|
||||
{
|
||||
for ( b = 0; b < nVars; b++ )
|
||||
{
|
||||
if ( (Cube & 3) == 1 || (Cube & 3) == 2 )
|
||||
nLits++;
|
||||
Cube >>= 2;
|
||||
}
|
||||
}
|
||||
return nLits;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes the cube and returns the number of literals in it.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cnf_IsopWriteCube( int Cube, int nVars, int * pVars, int * pLiterals )
|
||||
{
|
||||
int nLits = nVars, b;
|
||||
for ( b = 0; b < nVars; b++ )
|
||||
{
|
||||
if ( (Cube & 3) == 1 ) // value 0 --> write positive literal
|
||||
*pLiterals++ = 2 * pVars[b];
|
||||
else if ( (Cube & 3) == 2 ) // value 1 --> write negative literal
|
||||
*pLiterals++ = 2 * pVars[b] + 1;
|
||||
else
|
||||
nLits--;
|
||||
Cube >>= 2;
|
||||
}
|
||||
return nLits;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives CNF for the mapping.]
|
||||
|
||||
Description [The last argument shows the number of last outputs
|
||||
of the manager, which will not be converted into clauses but the
|
||||
new variables for which will be introduced.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
Cnf_Dat_t * pCnf;
|
||||
Cnf_Cut_t * pCut;
|
||||
Vec_Int_t * vCover, * vSopTemp;
|
||||
int OutVar, PoVar, pVars[32], * pLits, ** pClas;
|
||||
unsigned uTruth;
|
||||
int i, k, nLiterals, nClauses, Cube, Number;
|
||||
|
||||
// count the number of literals and clauses
|
||||
nLiterals = 1 + Aig_ManPoNum( p->pManAig ) + 3 * nOutputs;
|
||||
nClauses = 1 + Aig_ManPoNum( p->pManAig ) + nOutputs;
|
||||
Vec_PtrForEachEntry( vMapped, pObj, i )
|
||||
{
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
pCut = Cnf_ObjBestCut( pObj );
|
||||
|
||||
// positive polarity of the cut
|
||||
if ( pCut->nFanins < 5 )
|
||||
{
|
||||
uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
|
||||
nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
|
||||
assert( p->pSopSizes[uTruth] >= 0 );
|
||||
nClauses += p->pSopSizes[uTruth];
|
||||
}
|
||||
else
|
||||
{
|
||||
nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]);
|
||||
nClauses += Vec_IntSize(pCut->vIsop[1]);
|
||||
}
|
||||
// negative polarity of the cut
|
||||
if ( pCut->nFanins < 5 )
|
||||
{
|
||||
uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
|
||||
nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
|
||||
assert( p->pSopSizes[uTruth] >= 0 );
|
||||
nClauses += p->pSopSizes[uTruth];
|
||||
}
|
||||
else
|
||||
{
|
||||
nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]);
|
||||
nClauses += Vec_IntSize(pCut->vIsop[0]);
|
||||
}
|
||||
//printf( "%d ", nClauses-(1 + Aig_ManPoNum( p->pManAig )) );
|
||||
}
|
||||
//printf( "\n" );
|
||||
|
||||
// allocate CNF
|
||||
pCnf = ALLOC( Cnf_Dat_t, 1 );
|
||||
memset( pCnf, 0, sizeof(Cnf_Dat_t) );
|
||||
pCnf->nLiterals = nLiterals;
|
||||
pCnf->nClauses = nClauses;
|
||||
pCnf->pClauses = ALLOC( int *, nClauses + 1 );
|
||||
pCnf->pClauses[0] = ALLOC( int, nLiterals );
|
||||
pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
|
||||
|
||||
// create room for variable numbers
|
||||
pCnf->pVarNums = ALLOC( int, 1+Aig_ManObjIdMax(p->pManAig) );
|
||||
memset( pCnf->pVarNums, 0xff, sizeof(int) * (1+Aig_ManObjIdMax(p->pManAig)) );
|
||||
// assign variables to the last (nOutputs) POs
|
||||
Number = 1;
|
||||
if ( nOutputs )
|
||||
{
|
||||
assert( nOutputs == Aig_ManRegNum(p->pManAig) );
|
||||
Aig_ManForEachLiSeq( p->pManAig, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
}
|
||||
// assign variables to the internal nodes
|
||||
Vec_PtrForEachEntry( vMapped, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
// assign variables to the PIs and constant node
|
||||
Aig_ManForEachPi( p->pManAig, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
pCnf->pVarNums[Aig_ManConst1(p->pManAig)->Id] = Number++;
|
||||
pCnf->nVars = Number;
|
||||
|
||||
// assign the clauses
|
||||
vSopTemp = Vec_IntAlloc( 1 << 16 );
|
||||
pLits = pCnf->pClauses[0];
|
||||
pClas = pCnf->pClauses;
|
||||
Vec_PtrForEachEntry( vMapped, pObj, i )
|
||||
{
|
||||
pCut = Cnf_ObjBestCut( pObj );
|
||||
|
||||
// save variables of this cut
|
||||
OutVar = pCnf->pVarNums[ pObj->Id ];
|
||||
for ( k = 0; k < (int)pCut->nFanins; k++ )
|
||||
{
|
||||
pVars[k] = pCnf->pVarNums[ pCut->pFanins[k] ];
|
||||
assert( pVars[k] <= Aig_ManObjIdMax(p->pManAig) );
|
||||
}
|
||||
|
||||
// positive polarity of the cut
|
||||
if ( pCut->nFanins < 5 )
|
||||
{
|
||||
uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
|
||||
Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
|
||||
vCover = vSopTemp;
|
||||
}
|
||||
else
|
||||
vCover = pCut->vIsop[1];
|
||||
Vec_IntForEachEntry( vCover, Cube, k )
|
||||
{
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar;
|
||||
pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
|
||||
}
|
||||
|
||||
// negative polarity of the cut
|
||||
if ( pCut->nFanins < 5 )
|
||||
{
|
||||
uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
|
||||
Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
|
||||
vCover = vSopTemp;
|
||||
}
|
||||
else
|
||||
vCover = pCut->vIsop[0];
|
||||
Vec_IntForEachEntry( vCover, Cube, k )
|
||||
{
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar + 1;
|
||||
pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
|
||||
}
|
||||
}
|
||||
Vec_IntFree( vSopTemp );
|
||||
|
||||
// write the constant literal
|
||||
OutVar = pCnf->pVarNums[ Aig_ManConst1(p->pManAig)->Id ];
|
||||
assert( OutVar <= Aig_ManObjIdMax(p->pManAig) );
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar;
|
||||
|
||||
// write the output literals
|
||||
Aig_ManForEachPo( p->pManAig, pObj, i )
|
||||
{
|
||||
OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
|
||||
if ( i < Aig_ManPoNum(p->pManAig) - nOutputs )
|
||||
{
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
PoVar = pCnf->pVarNums[ pObj->Id ];
|
||||
// first clause
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * PoVar;
|
||||
*pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj);
|
||||
// second clause
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * PoVar + 1;
|
||||
*pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj);
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the correct number of literals and clauses was written
|
||||
assert( pLits - pCnf->pClauses[0] == nLiterals );
|
||||
assert( pClas - pCnf->pClauses == nClauses );
|
||||
return pCnf;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives a simple CNF for the AIG.]
|
||||
|
||||
Description [The last argument shows the number of last outputs
|
||||
of the manager, which will not be converted into clauses but the
|
||||
new variables for which will be introduced.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
Cnf_Dat_t * pCnf;
|
||||
int OutVar, PoVar, pVars[32], * pLits, ** pClas;
|
||||
int i, nLiterals, nClauses, Number;
|
||||
|
||||
// count the number of literals and clauses
|
||||
nLiterals = 1 + 7 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + 3 * nOutputs;
|
||||
nClauses = 1 + 3 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + nOutputs;
|
||||
|
||||
// allocate CNF
|
||||
pCnf = ALLOC( Cnf_Dat_t, 1 );
|
||||
memset( pCnf, 0, sizeof(Cnf_Dat_t) );
|
||||
pCnf->nLiterals = nLiterals;
|
||||
pCnf->nClauses = nClauses;
|
||||
pCnf->pClauses = ALLOC( int *, nClauses + 1 );
|
||||
pCnf->pClauses[0] = ALLOC( int, nLiterals );
|
||||
pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
|
||||
|
||||
// create room for variable numbers
|
||||
pCnf->pVarNums = ALLOC( int, 1+Aig_ManObjIdMax(p) );
|
||||
memset( pCnf->pVarNums, 0xff, sizeof(int) * (1+Aig_ManObjIdMax(p)) );
|
||||
// assign variables to the last (nOutputs) POs
|
||||
Number = 1;
|
||||
if ( nOutputs )
|
||||
{
|
||||
assert( nOutputs == Aig_ManRegNum(p) );
|
||||
Aig_ManForEachLiSeq( p, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
}
|
||||
// assign variables to the internal nodes
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
// assign variables to the PIs and constant node
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pCnf->pVarNums[pObj->Id] = Number++;
|
||||
pCnf->pVarNums[Aig_ManConst1(p)->Id] = Number++;
|
||||
pCnf->nVars = Number;
|
||||
/*
|
||||
// print CNF numbers
|
||||
printf( "SAT numbers of each node:\n" );
|
||||
Aig_ManForEachObj( p, pObj, i )
|
||||
printf( "%d=%d ", pObj->Id, pCnf->pVarNums[pObj->Id] );
|
||||
printf( "\n" );
|
||||
*/
|
||||
// assign the clauses
|
||||
pLits = pCnf->pClauses[0];
|
||||
pClas = pCnf->pClauses;
|
||||
Aig_ManForEachNode( p, pObj, i )
|
||||
{
|
||||
OutVar = pCnf->pVarNums[ pObj->Id ];
|
||||
pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
|
||||
pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ];
|
||||
|
||||
// positive phase
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar;
|
||||
*pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj);
|
||||
*pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj);
|
||||
// negative phase
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar + 1;
|
||||
*pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj);
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar + 1;
|
||||
*pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj);
|
||||
}
|
||||
|
||||
// write the constant literal
|
||||
OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ];
|
||||
assert( OutVar <= Aig_ManObjIdMax(p) );
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar;
|
||||
|
||||
// write the output literals
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
{
|
||||
OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
|
||||
if ( i < Aig_ManPoNum(p) - nOutputs )
|
||||
{
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
PoVar = pCnf->pVarNums[ pObj->Id ];
|
||||
// first clause
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * PoVar;
|
||||
*pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj);
|
||||
// second clause
|
||||
*pClas++ = pLits;
|
||||
*pLits++ = 2 * PoVar + 1;
|
||||
*pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj);
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the correct number of literals and clauses was written
|
||||
assert( pLits - pCnf->pClauses[0] == nLiterals );
|
||||
assert( pClas - pCnf->pClauses == nClauses );
|
||||
return pCnf;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cnf_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [AIG-to-CNF conversion.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: cnf_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cnf.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
SRC += src/aig/cnf/cnfCore.c \
|
||||
src/aig/cnf/cnfCut.c \
|
||||
src/aig/cnf/cnfData.c \
|
||||
src/aig/cnf/cnfMan.c \
|
||||
src/aig/cnf/cnfMap.c \
|
||||
src/aig/cnf/cnfPost.c \
|
||||
src/aig/cnf/cnfUtil.c \
|
||||
src/aig/cnf/cnfWrite.c
|
|
@ -0,0 +1,65 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [csw.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __CSW_H__
|
||||
#define __CSW_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== cnfCore.c ========================================================*/
|
||||
extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cswCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cswInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose )
|
||||
{
|
||||
Csw_Man_t * p;
|
||||
Aig_Man_t * pRes;
|
||||
Aig_Obj_t * pObj, * pObjNew, * pObjRes;
|
||||
int i, clk;
|
||||
clk = clock();
|
||||
// start the manager
|
||||
p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose );
|
||||
// set elementary cuts at the PIs
|
||||
Aig_ManForEachPi( p->pManRes, pObj, i )
|
||||
{
|
||||
Csw_ObjPrepareCuts( p, pObj, 1 );
|
||||
Csw_ObjAddRefs( p, pObj, Aig_ManPi(p->pManAig,i)->nRefs );
|
||||
}
|
||||
// process the nodes
|
||||
Aig_ManForEachNode( pAig, pObj, i )
|
||||
{
|
||||
// create the new node
|
||||
pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) );
|
||||
// check if this node can be represented using another node
|
||||
// pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
|
||||
// pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );
|
||||
// try recursively if resubsitution is used
|
||||
do {
|
||||
pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
|
||||
pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );
|
||||
pObjNew = pObjRes;
|
||||
} while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) );
|
||||
// save the resulting node
|
||||
Csw_ObjSetEquiv( p, pObj, pObjRes );
|
||||
// add to the reference counter
|
||||
Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs );
|
||||
}
|
||||
// add the POs
|
||||
Aig_ManForEachPo( pAig, pObj, i )
|
||||
Aig_ObjCreatePo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) );
|
||||
// remove dangling nodes
|
||||
Aig_ManCleanup( p->pManRes );
|
||||
// return the resulting manager
|
||||
p->timeTotal = clock() - clk;
|
||||
p->timeOther = p->timeTotal - p->timeCuts - p->timeHash;
|
||||
pRes = p->pManRes;
|
||||
Csw_ManStop( p );
|
||||
return pRes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,602 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cswCut.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cswInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compute the cost of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i, Cost = 0;
|
||||
assert( pCut->nFanins > 0 );
|
||||
Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
|
||||
{
|
||||
// Cost += pLeaf->nRefs;
|
||||
Cost += Csw_ObjRefs( p, pLeaf );
|
||||
// printf( "%d ", pLeaf->nRefs );
|
||||
}
|
||||
//printf( "\n" );
|
||||
return Cost * 100 / pCut->nFanins;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compute the cost of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
float Cost = 0.0;
|
||||
int i;
|
||||
assert( pCut->nFanins > 0 );
|
||||
Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
|
||||
Cost += (float)1.0/pLeaf->nRefs;
|
||||
return 1/Cost;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the next free cut to use.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Csw_Cut_t * pCut, * pCutMax;
|
||||
int i;
|
||||
pCutMax = NULL;
|
||||
Csw_ObjForEachCut( p, pObj, pCut, i )
|
||||
{
|
||||
if ( pCut->nFanins == 0 )
|
||||
return pCut;
|
||||
if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost )
|
||||
pCutMax = pCut;
|
||||
}
|
||||
assert( pCutMax != NULL );
|
||||
pCutMax->nFanins = 0;
|
||||
return pCutMax;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Cut_TruthPhase( Csw_Cut_t * pCut, Csw_Cut_t * pCut1 )
|
||||
{
|
||||
unsigned uPhase = 0;
|
||||
int i, k;
|
||||
for ( i = k = 0; i < pCut->nFanins; i++ )
|
||||
{
|
||||
if ( k == pCut1->nFanins )
|
||||
break;
|
||||
if ( pCut->pFanins[i] < pCut1->pFanins[k] )
|
||||
continue;
|
||||
assert( pCut->pFanins[i] == pCut1->pFanins[k] );
|
||||
uPhase |= (1 << i);
|
||||
k++;
|
||||
}
|
||||
return uPhase;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs truth table computation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 )
|
||||
{
|
||||
// permute the first table
|
||||
if ( fCompl0 )
|
||||
Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
|
||||
else
|
||||
Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
|
||||
Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 );
|
||||
// permute the second table
|
||||
if ( fCompl1 )
|
||||
Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
|
||||
else
|
||||
Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
|
||||
Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 );
|
||||
// produce the resulting table
|
||||
Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax );
|
||||
// assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) );
|
||||
return Csw_CutTruth(pCut);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs support minimization for the truth table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
unsigned * pTruth;
|
||||
int uSupp, nFansNew, i, k;
|
||||
// get truth table
|
||||
pTruth = Csw_CutTruth( pCut );
|
||||
// get support
|
||||
uSupp = Kit_TruthSupport( pTruth, p->nLeafMax );
|
||||
// get the new support size
|
||||
nFansNew = Kit_WordCountOnes( uSupp );
|
||||
// check if there are redundant variables
|
||||
if ( nFansNew == pCut->nFanins )
|
||||
return nFansNew;
|
||||
assert( nFansNew < pCut->nFanins );
|
||||
// minimize support
|
||||
Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 );
|
||||
for ( i = k = 0; i < pCut->nFanins; i++ )
|
||||
if ( uSupp & (1 << i) )
|
||||
pCut->pFanins[k++] = pCut->pFanins[i];
|
||||
assert( k == nFansNew );
|
||||
pCut->nFanins = nFansNew;
|
||||
// assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) );
|
||||
//Extra_PrintBinary( stdout, pTruth, (1<<p->nLeafMax) ); printf( "\n" );
|
||||
return nFansNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pDom is contained in pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_Cut_t * pCut )
|
||||
{
|
||||
int i, k;
|
||||
for ( i = 0; i < (int)pDom->nFanins; i++ )
|
||||
{
|
||||
for ( k = 0; k < (int)pCut->nFanins; k++ )
|
||||
if ( pDom->pFanins[i] == pCut->pFanins[k] )
|
||||
break;
|
||||
if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut
|
||||
return 0;
|
||||
}
|
||||
// every node in pDom is contained in pCut
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the cut is contained.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut )
|
||||
{
|
||||
Csw_Cut_t * pTemp;
|
||||
int i;
|
||||
// go through the cuts of the node
|
||||
Csw_ObjForEachCut( p, pObj, pTemp, i )
|
||||
{
|
||||
if ( pTemp->nFanins < 2 )
|
||||
continue;
|
||||
if ( pTemp == pCut )
|
||||
continue;
|
||||
if ( pTemp->nFanins > pCut->nFanins )
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( Csw_CutCheckDominance( pCut, pTemp ) )
|
||||
{
|
||||
// remove contained cut
|
||||
pTemp->nFanins = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( Csw_CutCheckDominance( pTemp, pCut ) )
|
||||
{
|
||||
// remove the given
|
||||
pCut->nFanins = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_Cut_t * pC )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nFanins >= pC1->nFanins );
|
||||
// the case of the largest cut sizes
|
||||
if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax )
|
||||
{
|
||||
for ( i = 0; i < pC0->nFanins; i++ )
|
||||
if ( pC0->pFanins[i] != pC1->pFanins[i] )
|
||||
return 0;
|
||||
for ( i = 0; i < pC0->nFanins; i++ )
|
||||
pC->pFanins[i] = pC0->pFanins[i];
|
||||
pC->nFanins = pC0->nFanins;
|
||||
return 1;
|
||||
}
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nFanins == p->nLeafMax )
|
||||
{
|
||||
for ( i = 0; i < pC1->nFanins; i++ )
|
||||
{
|
||||
for ( k = pC0->nFanins - 1; k >= 0; k-- )
|
||||
if ( pC0->pFanins[k] == pC1->pFanins[i] )
|
||||
break;
|
||||
if ( k == -1 ) // did not find
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < pC0->nFanins; i++ )
|
||||
pC->pFanins[i] = pC0->pFanins[i];
|
||||
pC->nFanins = pC0->nFanins;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compare two cuts with different numbers
|
||||
i = k = 0;
|
||||
for ( c = 0; c < p->nLeafMax; c++ )
|
||||
{
|
||||
if ( k == pC1->nFanins )
|
||||
{
|
||||
if ( i == pC0->nFanins )
|
||||
{
|
||||
pC->nFanins = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pFanins[c] = pC0->pFanins[i++];
|
||||
continue;
|
||||
}
|
||||
if ( i == pC0->nFanins )
|
||||
{
|
||||
if ( k == pC1->nFanins )
|
||||
{
|
||||
pC->nFanins = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pFanins[c] = pC1->pFanins[k++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pFanins[i] < pC1->pFanins[k] )
|
||||
{
|
||||
pC->pFanins[c] = pC0->pFanins[i++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pFanins[i] > pC1->pFanins[k] )
|
||||
{
|
||||
pC->pFanins[c] = pC1->pFanins[k++];
|
||||
continue;
|
||||
}
|
||||
pC->pFanins[c] = pC0->pFanins[i++];
|
||||
k++;
|
||||
}
|
||||
if ( i < pC0->nFanins || k < pC1->nFanins )
|
||||
return 0;
|
||||
pC->nFanins = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut )
|
||||
{
|
||||
assert( p->nLeafMax > 0 );
|
||||
// merge the nodes
|
||||
if ( pCut0->nFanins < pCut1->nFanins )
|
||||
{
|
||||
if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
|
||||
return 0;
|
||||
}
|
||||
pCut->uSign = pCut0->uSign | pCut1->uSign;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Consider cut with more than 2 fanins having 2 true variables.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pRes, * pIn0, * pIn1;
|
||||
int nVars, uTruth, fCompl = 0;
|
||||
assert( pCut->nFanins > 2 );
|
||||
// minimize support of this cut
|
||||
nVars = Csw_CutSupportMinimize( p, pCut );
|
||||
assert( nVars == 2 );
|
||||
// get the fanins
|
||||
pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] );
|
||||
pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] );
|
||||
// derive the truth table
|
||||
uTruth = 0xF & *Csw_CutTruth(pCut);
|
||||
if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 )
|
||||
{
|
||||
uTruth = 0xF & ~uTruth;
|
||||
fCompl = 1;
|
||||
}
|
||||
// compute the result
|
||||
pRes = NULL;
|
||||
if ( uTruth == 1 ) // 0001 // 1110 14
|
||||
pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) );
|
||||
if ( uTruth == 2 ) // 0010 // 1101 13
|
||||
pRes = Aig_And( p->pManRes, pIn0 , Aig_Not(pIn1) );
|
||||
if ( uTruth == 4 ) // 0100 // 1011 11
|
||||
pRes = Aig_And( p->pManRes, Aig_Not(pIn0), pIn1 );
|
||||
if ( uTruth == 8 ) // 1000 // 0111 7
|
||||
pRes = Aig_And( p->pManRes, pIn0 , pIn1 );
|
||||
if ( pRes )
|
||||
pRes = Aig_NotCond( pRes, fCompl );
|
||||
return pRes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
|
||||
{
|
||||
Csw_Cut_t * pCutSet, * pCut;
|
||||
int i;
|
||||
// create the cutset of the node
|
||||
pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
|
||||
Csw_ObjSetCuts( p, pObj, pCutSet );
|
||||
Csw_ObjForEachCut( p, pObj, pCut, i )
|
||||
{
|
||||
pCut->nFanins = 0;
|
||||
pCut->iNode = pObj->Id;
|
||||
pCut->nCutSize = p->nCutSize;
|
||||
pCut->nLeafMax = p->nLeafMax;
|
||||
}
|
||||
// add unit cut if needed
|
||||
if ( fTriv )
|
||||
{
|
||||
pCut = pCutSet;
|
||||
pCut->Cost = 0;
|
||||
pCut->iNode = pObj->Id;
|
||||
pCut->nFanins = 1;
|
||||
pCut->pFanins[0] = pObj->Id;
|
||||
pCut->uSign = Aig_ObjCutSign( pObj->Id );
|
||||
memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords );
|
||||
}
|
||||
return pCutSet;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives cuts for one node and sweeps this node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
|
||||
{
|
||||
int fUseResub = 1;
|
||||
Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet;
|
||||
Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
|
||||
Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
|
||||
Aig_Obj_t * pObjNew;
|
||||
unsigned * pTruth;
|
||||
int i, k, nVars, nFanins, iVar, clk;
|
||||
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
return pObj;
|
||||
if ( Csw_ObjCuts(p, pObj) )
|
||||
return pObj;
|
||||
// the node is not processed yet
|
||||
assert( Csw_ObjCuts(p, pObj) == NULL );
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
|
||||
// set up the first cut
|
||||
pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv );
|
||||
|
||||
// compute pair-wise cut combinations while checking table
|
||||
Csw_ObjForEachCut( p, pFanin0, pCut0, i )
|
||||
if ( pCut0->nFanins > 0 )
|
||||
Csw_ObjForEachCut( p, pFanin1, pCut1, k )
|
||||
if ( pCut1->nFanins > 0 )
|
||||
{
|
||||
// make sure K-feasible cut exists
|
||||
if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax )
|
||||
continue;
|
||||
// get the next cut of this node
|
||||
pCut = Csw_CutFindFree( p, pObj );
|
||||
clk = clock();
|
||||
// assemble the new cut
|
||||
if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) )
|
||||
{
|
||||
assert( pCut->nFanins == 0 );
|
||||
continue;
|
||||
}
|
||||
// check containment
|
||||
if ( Csw_CutFilter( p, pObj, pCut ) )
|
||||
{
|
||||
assert( pCut->nFanins == 0 );
|
||||
continue;
|
||||
}
|
||||
// create its truth table
|
||||
pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
|
||||
// support minimize the truth table
|
||||
nFanins = pCut->nFanins;
|
||||
// nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation
|
||||
nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax );
|
||||
p->timeCuts += clock() - clk;
|
||||
|
||||
// check for trivial truth tables
|
||||
if ( nVars == 0 )
|
||||
{
|
||||
p->nNodesTriv0++;
|
||||
return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) );
|
||||
}
|
||||
if ( nVars == 1 )
|
||||
{
|
||||
p->nNodesTriv1++;
|
||||
iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) );
|
||||
assert( iVar < pCut->nFanins );
|
||||
return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) );
|
||||
}
|
||||
if ( nVars == 2 && nFanins > 2 && fUseResub )
|
||||
{
|
||||
if ( pObjNew = Csw_ObjTwoVarCut( p, pCut ) )
|
||||
{
|
||||
p->nNodesTriv2++;
|
||||
return pObjNew;
|
||||
}
|
||||
}
|
||||
|
||||
// check if an equivalent node with the same cut exists
|
||||
clk = clock();
|
||||
pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL;
|
||||
p->timeHash += clock() - clk;
|
||||
if ( pObjNew )
|
||||
{
|
||||
p->nNodesCuts++;
|
||||
return pObjNew;
|
||||
}
|
||||
|
||||
// assign the cost
|
||||
pCut->Cost = Csw_CutFindCost( p, pCut );
|
||||
assert( pCut->nFanins > 0 );
|
||||
assert( pCut->Cost > 0 );
|
||||
}
|
||||
p->nNodesTried++;
|
||||
|
||||
// load the resulting cuts into the table
|
||||
clk = clock();
|
||||
Csw_ObjForEachCut( p, pObj, pCut, i )
|
||||
{
|
||||
if ( pCut->nFanins > 2 )
|
||||
{
|
||||
assert( pCut->Cost > 0 );
|
||||
Csw_TableCutInsert( p, pCut );
|
||||
}
|
||||
}
|
||||
p->timeHash += clock() - clk;
|
||||
|
||||
// return the node if could not replace it
|
||||
return pObj;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cswInt.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __CSW_INT_H__
|
||||
#define __CSW_INT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "aig.h"
|
||||
#include "dar.h"
|
||||
#include "kit.h"
|
||||
#include "csw.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Csw_Man_t_ Csw_Man_t;
|
||||
typedef struct Csw_Cut_t_ Csw_Cut_t;
|
||||
|
||||
// the cut used to represent node in the AIG
|
||||
struct Csw_Cut_t_
|
||||
{
|
||||
Csw_Cut_t * pNext; // the next cut in the table
|
||||
int Cost; // the cost of the cut
|
||||
// float Cost; // the cost of the cut
|
||||
unsigned uSign; // cut signature
|
||||
int iNode; // the node, for which it is the cut
|
||||
short nCutSize; // the number of bytes in the cut
|
||||
char nLeafMax; // the maximum number of fanins
|
||||
char nFanins; // the current number of fanins
|
||||
int pFanins[0]; // the fanins (followed by the truth table)
|
||||
};
|
||||
|
||||
// the CNF computation manager
|
||||
struct Csw_Man_t_
|
||||
{
|
||||
// AIG manager
|
||||
Aig_Man_t * pManAig; // the input AIG manager
|
||||
Aig_Man_t * pManRes; // the output AIG manager
|
||||
Aig_Obj_t ** pEquiv; // the equivalent nodes in the resulting manager
|
||||
Csw_Cut_t ** pCuts; // the cuts for each node in the output manager
|
||||
int * pnRefs; // the number of references of each new node
|
||||
// hash table for cuts
|
||||
Csw_Cut_t ** pTable; // the table composed of cuts
|
||||
int nTableSize; // the size of hash table
|
||||
// parameters
|
||||
int nCutsMax; // the max number of cuts at the node
|
||||
int nLeafMax; // the max number of leaves of a cut
|
||||
int fVerbose; // enables verbose output
|
||||
// internal variables
|
||||
int nCutSize; // the number of bytes needed to store one cut
|
||||
int nTruthWords; // the number of truth table words
|
||||
Aig_MmFixed_t * pMemCuts; // memory manager for cuts
|
||||
unsigned * puTemp[4]; // used for the truth table computation
|
||||
// statistics
|
||||
int nNodesTriv0; // the number of trivial nodes
|
||||
int nNodesTriv1; // the number of trivial nodes
|
||||
int nNodesTriv2; // the number of trivial nodes
|
||||
int nNodesCuts; // the number of rewritten nodes
|
||||
int nNodesTried; // the number of nodes tried
|
||||
int timeCuts; // time to compute the cut and its truth table
|
||||
int timeHash; // time for hashing cuts
|
||||
int timeOther; // other time
|
||||
int timeTotal; // total time
|
||||
};
|
||||
|
||||
static inline int Csw_CutLeaveNum( Csw_Cut_t * pCut ) { return pCut->nFanins; }
|
||||
static inline int * Csw_CutLeaves( Csw_Cut_t * pCut ) { return pCut->pFanins; }
|
||||
static inline unsigned * Csw_CutTruth( Csw_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); }
|
||||
static inline Csw_Cut_t * Csw_CutNext( Csw_Cut_t * pCut ) { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize); }
|
||||
|
||||
static inline int Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pnRefs[pObj->Id]; }
|
||||
static inline void Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs ) { p->pnRefs[pObj->Id] += nRefs; }
|
||||
|
||||
static inline Csw_Cut_t * Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; }
|
||||
static inline void Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; }
|
||||
|
||||
static inline Aig_Obj_t * Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquiv[pObj->Id]; }
|
||||
static inline void Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; }
|
||||
|
||||
static inline Aig_Obj_t * Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; }
|
||||
static inline Aig_Obj_t * Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// iterator over cuts of the node
|
||||
#define Csw_ObjForEachCut( p, pObj, pCut, i ) \
|
||||
for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) )
|
||||
// iterator over leaves of the cut
|
||||
#define Csw_CutForEachLeaf( p, pCut, pLeaf, i ) \
|
||||
for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== cnfCut.c ========================================================*/
|
||||
extern Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
|
||||
extern Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
|
||||
/*=== cnfMan.c ========================================================*/
|
||||
extern Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose );
|
||||
extern void Csw_ManStop( Csw_Man_t * p );
|
||||
/*=== cnfTable.c ========================================================*/
|
||||
extern int Csw_TableCountCuts( Csw_Man_t * p );
|
||||
extern void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut );
|
||||
extern Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cswMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cswInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the cut sweeping manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose )
|
||||
{
|
||||
Csw_Man_t * p;
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
assert( nCutsMax >= 2 );
|
||||
assert( nLeafMax <= 16 );
|
||||
// allocate the fraiging manager
|
||||
p = ALLOC( Csw_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Csw_Man_t) );
|
||||
p->nCutsMax = nCutsMax;
|
||||
p->nLeafMax = nLeafMax;
|
||||
p->fVerbose = fVerbose;
|
||||
p->pManAig = pMan;
|
||||
// create the new manager
|
||||
p->pManRes = Aig_ManStartFrom( pMan );
|
||||
assert( Aig_ManPiNum(p->pManAig) == Aig_ManPiNum(p->pManRes) );
|
||||
// allocate room for cuts and equivalent nodes
|
||||
p->pnRefs = ALLOC( int, Aig_ManObjIdMax(pMan) + 1 );
|
||||
p->pEquiv = ALLOC( Aig_Obj_t *, Aig_ManObjIdMax(pMan) + 1 );
|
||||
p->pCuts = ALLOC( Csw_Cut_t *, Aig_ManObjIdMax(pMan) + 1 );
|
||||
memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * (Aig_ManObjIdMax(pMan) + 1) );
|
||||
memset( p->pnRefs, 0, sizeof(int) * (Aig_ManObjIdMax(pMan) + 1) );
|
||||
// allocate memory manager
|
||||
p->nTruthWords = Aig_TruthWordNum(nLeafMax);
|
||||
p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords;
|
||||
p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 );
|
||||
// allocate hash table for cuts
|
||||
p->nTableSize = Aig_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 );
|
||||
p->pTable = ALLOC( Csw_Cut_t *, p->nTableSize );
|
||||
memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
|
||||
// set the pointers to the available fraig nodes
|
||||
Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) );
|
||||
Aig_ManForEachPi( p->pManAig, pObj, i )
|
||||
Csw_ObjSetEquiv( p, pObj, Aig_ManPi(p->pManRes, i) );
|
||||
// room for temporary truth tables
|
||||
p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords );
|
||||
p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
|
||||
p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
|
||||
p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the fraiging manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Csw_ManStop( Csw_Man_t * p )
|
||||
{
|
||||
if ( p->fVerbose )
|
||||
{
|
||||
int nNodesBeg = Aig_ManNodeNum(p->pManAig);
|
||||
int nNodesEnd = Aig_ManNodeNum(p->pManRes);
|
||||
printf( "Beg = %7d. End = %7d. (%6.2f %%) Try = %7d. Cuts = %8d.\n",
|
||||
nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg,
|
||||
p->nNodesTried, Csw_TableCountCuts( p ) );
|
||||
printf( "Triv0 = %6d. Triv1 = %6d. Triv2 = %6d. Cut-replace = %6d.\n",
|
||||
p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts );
|
||||
PRTP( "Cuts ", p->timeCuts, p->timeTotal );
|
||||
PRTP( "Hashing ", p->timeHash, p->timeTotal );
|
||||
PRTP( "Other ", p->timeOther, p->timeTotal );
|
||||
PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
|
||||
}
|
||||
free( p->puTemp[0] );
|
||||
Aig_MmFixedStop( p->pMemCuts, 0 );
|
||||
free( p->pnRefs );
|
||||
free( p->pEquiv );
|
||||
free( p->pCuts );
|
||||
free( p->pTable );
|
||||
free( p );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cswTable.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cswInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes hash value of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned Csw_CutHash( Csw_Cut_t * pCut )
|
||||
{
|
||||
static int s_FPrimes[128] = {
|
||||
1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
|
||||
1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
|
||||
2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
|
||||
2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
|
||||
3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
|
||||
3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
|
||||
4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
|
||||
4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
|
||||
5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
|
||||
6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
|
||||
6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
|
||||
7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
|
||||
8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
|
||||
};
|
||||
unsigned uHash;
|
||||
int i;
|
||||
assert( pCut->nFanins <= 16 );
|
||||
uHash = 0;
|
||||
for ( i = 0; i < pCut->nFanins; i++ )
|
||||
uHash ^= pCut->pFanins[i] * s_FPrimes[i];
|
||||
return uHash;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the total number of cuts in the table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Csw_TableCountCuts( Csw_Man_t * p )
|
||||
{
|
||||
Csw_Cut_t * pEnt;
|
||||
int i, Counter = 0;
|
||||
for ( i = 0; i < p->nTableSize; i++ )
|
||||
for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext )
|
||||
Counter++;
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds the cut to the hash table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
int iEntry = Csw_CutHash(pCut) % p->nTableSize;
|
||||
pCut->pNext = p->pTable[iEntry];
|
||||
p->pTable[iEntry] = pCut;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns an equivalent node if it exists.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pRes = NULL;
|
||||
Csw_Cut_t * pEnt;
|
||||
unsigned * pTruthNew, * pTruthOld;
|
||||
int iEntry = Csw_CutHash(pCut) % p->nTableSize;
|
||||
for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext )
|
||||
{
|
||||
if ( pEnt->nFanins != pCut->nFanins )
|
||||
continue;
|
||||
if ( pEnt->uSign != pCut->uSign )
|
||||
continue;
|
||||
if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) )
|
||||
continue;
|
||||
pTruthOld = Csw_CutTruth(pEnt);
|
||||
pTruthNew = Csw_CutTruth(pCut);
|
||||
if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) )
|
||||
{
|
||||
if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) )
|
||||
{
|
||||
pRes = Aig_ManObj( p->pManRes, pEnt->iNode );
|
||||
assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) )
|
||||
{
|
||||
pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) );
|
||||
assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pRes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [csw_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Cut sweeping.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 11, 2007.]
|
||||
|
||||
Revision [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cswInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
SRC += src/aig/csw/cswCore.c \
|
||||
src/aig/csw/cswCut.c \
|
||||
src/aig/csw/cswMan.c \
|
||||
src/aig/csw/cswTable.c
|
|
@ -0,0 +1,101 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [dar.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: dar.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __DAR_H__
|
||||
#define __DAR_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Dar_RwrPar_t_ Dar_RwrPar_t;
|
||||
typedef struct Dar_RefPar_t_ Dar_RefPar_t;
|
||||
|
||||
struct Dar_RwrPar_t_
|
||||
{
|
||||
int nCutsMax; // the maximum number of cuts to try
|
||||
int nSubgMax; // the maximum number of subgraphs to try
|
||||
int fFanout; // support fanout representation
|
||||
int fUpdateLevel; // update level
|
||||
int fUseZeros; // performs zero-cost replacement
|
||||
int fVerbose; // enables verbose output
|
||||
int fVeryVerbose; // enables very verbose output
|
||||
};
|
||||
|
||||
struct Dar_RefPar_t_
|
||||
{
|
||||
int nMffcMin; // the min MFFC size for which refactoring is used
|
||||
int nLeafMax; // the max number of leaves of a cut
|
||||
int nCutsMax; // the max number of cuts to consider
|
||||
int fExtend; // extends the cut below MFFC
|
||||
int fUpdateLevel; // updates the level after each move
|
||||
int fUseZeros; // perform zero-cost replacements
|
||||
int fVerbose; // verbosity level
|
||||
int fVeryVerbose; // enables very verbose output
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== darBalance.c ========================================================*/
|
||||
extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel );
|
||||
/*=== darCore.c ========================================================*/
|
||||
extern void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars );
|
||||
extern int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars );
|
||||
extern Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax );
|
||||
/*=== darRefact.c ========================================================*/
|
||||
extern void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars );
|
||||
extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars );
|
||||
/*=== darScript.c ========================================================*/
|
||||
extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig );
|
||||
extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose );
|
||||
extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darBalance.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Algebraic AIG balancing.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
|
||||
static Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
|
||||
static int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper );
|
||||
static void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
|
||||
static void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj );
|
||||
static Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs algebraic balancing of the AIG.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel )
|
||||
{
|
||||
Aig_Man_t * pNew;
|
||||
Aig_Obj_t * pObj, * pDriver, * pObjNew;
|
||||
Vec_Vec_t * vStore;
|
||||
int i;
|
||||
// create the new manager
|
||||
pNew = Aig_ManStart( Aig_ManObjIdMax(p) + 1 );
|
||||
pNew->nRegs = p->nRegs;
|
||||
pNew->nAsserts = p->nAsserts;
|
||||
// map the PI nodes
|
||||
Aig_ManCleanData( p );
|
||||
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
|
||||
Aig_ManForEachPi( p, pObj, i )
|
||||
pObj->pData = Aig_ObjCreatePi(pNew);
|
||||
// balance the AIG
|
||||
vStore = Vec_VecAlloc( 50 );
|
||||
Aig_ManForEachPo( p, pObj, i )
|
||||
{
|
||||
pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
|
||||
pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
|
||||
Aig_ObjCreatePo( pNew, pObjNew );
|
||||
}
|
||||
Vec_VecFree( vStore );
|
||||
// remove dangling nodes
|
||||
if ( i = Aig_ManCleanup( pNew ) )
|
||||
printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
|
||||
// check the resulting AIG
|
||||
if ( !Aig_ManCheck(pNew) )
|
||||
printf( "Dar_ManBalance(): The check has failed.\n" );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the new node constructed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
|
||||
{
|
||||
Aig_Obj_t * pObjNew;
|
||||
Vec_Ptr_t * vSuper;
|
||||
int i;
|
||||
assert( !Aig_IsComplement(pObjOld) );
|
||||
assert( !Aig_ObjIsBuf(pObjOld) );
|
||||
// return if the result is known
|
||||
if ( pObjOld->pData )
|
||||
return pObjOld->pData;
|
||||
assert( Aig_ObjIsNode(pObjOld) );
|
||||
// get the implication supergate
|
||||
vSuper = Dar_BalanceCone( pObjOld, vStore, Level );
|
||||
// check if supergate contains two nodes in the opposite polarity
|
||||
if ( vSuper->nSize == 0 )
|
||||
return pObjOld->pData = Aig_ManConst0(pNew);
|
||||
if ( Vec_PtrSize(vSuper) < 2 )
|
||||
printf( "BUG!\n" );
|
||||
// for each old node, derive the new well-balanced node
|
||||
for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
|
||||
{
|
||||
pObjNew = Dar_Balance_rec( pNew, Aig_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
|
||||
vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement(vSuper->pArray[i]) );
|
||||
}
|
||||
// build the supergate
|
||||
pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel );
|
||||
// make sure the balanced node is not assigned
|
||||
// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level );
|
||||
assert( pObjOld->pData == NULL );
|
||||
return pObjOld->pData = pObjNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes of the supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
|
||||
{
|
||||
int RetValue1, RetValue2, i;
|
||||
// check if the node is visited
|
||||
if ( Aig_Regular(pObj)->fMarkB )
|
||||
{
|
||||
// check if the node occurs in the same polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == pObj )
|
||||
return 1;
|
||||
// check if the node is present in the opposite polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == Aig_Not(pObj) )
|
||||
return -1;
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
// if the new node is complemented or a PI, another gate begins
|
||||
if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) )
|
||||
{
|
||||
Vec_PtrPush( vSuper, pObj );
|
||||
Aig_Regular(pObj)->fMarkB = 1;
|
||||
return 0;
|
||||
}
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
// go through the branches
|
||||
RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
|
||||
RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
|
||||
if ( RetValue1 == -1 || RetValue2 == -1 )
|
||||
return -1;
|
||||
// return 1 if at least one branch has a duplicate
|
||||
return RetValue1 || RetValue2;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes of the supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
int RetValue, i;
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
// extend the storage
|
||||
if ( Vec_VecSize( vStore ) <= Level )
|
||||
Vec_VecPush( vStore, Level, 0 );
|
||||
// get the temporary array of nodes
|
||||
vNodes = Vec_VecEntry( vStore, Level );
|
||||
Vec_PtrClear( vNodes );
|
||||
// collect the nodes in the implication supergate
|
||||
RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes );
|
||||
assert( vNodes->nSize > 1 );
|
||||
// unmark the visited nodes
|
||||
Vec_PtrForEachEntry( vNodes, pObj, i )
|
||||
Aig_Regular(pObj)->fMarkB = 0;
|
||||
// if we found the node and its complement in the same implication supergate,
|
||||
// return empty set of nodes (meaning that we should use constant-0 node)
|
||||
if ( RetValue == -1 )
|
||||
vNodes->nSize = 0;
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
|
||||
{
|
||||
int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2));
|
||||
if ( Diff > 0 )
|
||||
return -1;
|
||||
if ( Diff < 0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Builds implication supergate.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel )
|
||||
{
|
||||
Aig_Obj_t * pObj1, * pObj2;
|
||||
int LeftBound;
|
||||
assert( vSuper->nSize > 1 );
|
||||
// sort the new nodes by level in the decreasing order
|
||||
Vec_PtrSort( vSuper, Aig_NodeCompareLevelsDecrease );
|
||||
// balance the nodes
|
||||
while ( vSuper->nSize > 1 )
|
||||
{
|
||||
// find the left bound on the node to be paired
|
||||
LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper );
|
||||
// find the node that can be shared (if no such node, randomize choice)
|
||||
Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR );
|
||||
// pull out the last two nodes
|
||||
pObj1 = Vec_PtrPop(vSuper);
|
||||
pObj2 = Vec_PtrPop(vSuper);
|
||||
Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) );
|
||||
}
|
||||
return Vec_PtrEntry(vSuper, 0);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds the left bound on the next candidate to be paired.]
|
||||
|
||||
Description [The nodes in the array are in the decreasing order of levels.
|
||||
The last node in the array has the smallest level. By default it would be paired
|
||||
with the next node on the left. However, it may be possible to pair it with some
|
||||
other node on the left, in such a way that the new node is shared. This procedure
|
||||
finds the index of the left-most node, which can be paired with the last node.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper )
|
||||
{
|
||||
Aig_Obj_t * pObjRight, * pObjLeft;
|
||||
int Current;
|
||||
// if two or less nodes, pair with the first
|
||||
if ( Vec_PtrSize(vSuper) < 3 )
|
||||
return 0;
|
||||
// set the pointer to the one before the last
|
||||
Current = Vec_PtrSize(vSuper) - 2;
|
||||
pObjRight = Vec_PtrEntry( vSuper, Current );
|
||||
// go through the nodes to the left of this one
|
||||
for ( Current--; Current >= 0; Current-- )
|
||||
{
|
||||
// get the next node on the left
|
||||
pObjLeft = Vec_PtrEntry( vSuper, Current );
|
||||
// if the level of this node is different, quit the loop
|
||||
if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) )
|
||||
break;
|
||||
}
|
||||
Current++;
|
||||
// get the node, for which the equality holds
|
||||
pObjLeft = Vec_PtrEntry( vSuper, Current );
|
||||
assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) );
|
||||
return Current;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Moves closer to the end the node that is best for sharing.]
|
||||
|
||||
Description [If there is no node with sharing, randomly chooses one of
|
||||
the legal nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
|
||||
{
|
||||
Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
|
||||
int RightBound, i;
|
||||
// get the right bound
|
||||
RightBound = Vec_PtrSize(vSuper) - 2;
|
||||
assert( LeftBound <= RightBound );
|
||||
if ( LeftBound == RightBound )
|
||||
return;
|
||||
// get the two last nodes
|
||||
pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 );
|
||||
pObj2 = Vec_PtrEntry( vSuper, RightBound );
|
||||
if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 )
|
||||
return;
|
||||
// find the first node that can be shared
|
||||
for ( i = RightBound; i >= LeftBound; i-- )
|
||||
{
|
||||
pObj3 = Vec_PtrEntry( vSuper, i );
|
||||
if ( Aig_Regular(pObj3) == p->pConst1 )
|
||||
{
|
||||
Vec_PtrWriteEntry( vSuper, i, pObj2 );
|
||||
Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
|
||||
return;
|
||||
}
|
||||
pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND );
|
||||
if ( Aig_TableLookup( p, pGhost ) )
|
||||
{
|
||||
if ( pObj3 == pObj2 )
|
||||
return;
|
||||
Vec_PtrWriteEntry( vSuper, i, pObj2 );
|
||||
Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// we did not find the node to share, randomize choice
|
||||
{
|
||||
int Choice = rand() % (RightBound - LeftBound + 1);
|
||||
pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
|
||||
if ( pObj3 == pObj2 )
|
||||
return;
|
||||
Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
|
||||
Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Inserts a new node in the order by levels.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pObj1, * pObj2;
|
||||
int i;
|
||||
if ( Vec_PtrPushUnique(vStore, pObj) )
|
||||
return;
|
||||
// find the p of the node
|
||||
for ( i = vStore->nSize-1; i > 0; i-- )
|
||||
{
|
||||
pObj1 = vStore->pArray[i ];
|
||||
pObj2 = vStore->pArray[i-1];
|
||||
if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) )
|
||||
break;
|
||||
vStore->pArray[i ] = pObj2;
|
||||
vStore->pArray[i-1] = pObj1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Core of the rewriting package.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the structure with default assignment of parameters.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars )
|
||||
{
|
||||
memset( pPars, 0, sizeof(Dar_RwrPar_t) );
|
||||
pPars->nCutsMax = 8; // 8
|
||||
pPars->nSubgMax = 5; // 5 is a "magic number"
|
||||
pPars->fFanout = 1;
|
||||
pPars->fUpdateLevel = 0;
|
||||
pPars->fUseZeros = 0;
|
||||
pPars->fVerbose = 0;
|
||||
pPars->fVeryVerbose = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
|
||||
{
|
||||
Dar_Man_t * p;
|
||||
ProgressBar * pProgress;
|
||||
Dar_Cut_t * pCut;
|
||||
Aig_Obj_t * pObj, * pObjNew;
|
||||
int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required;
|
||||
int clk = 0, clkStart;
|
||||
// prepare the library
|
||||
Dar_LibPrepare( pPars->nSubgMax );
|
||||
// create rewriting manager
|
||||
p = Dar_ManStart( pAig, pPars );
|
||||
// remove dangling nodes
|
||||
Aig_ManCleanup( pAig );
|
||||
// if updating levels is requested, start fanout and timing
|
||||
if ( p->pPars->fFanout )
|
||||
Aig_ManFanoutStart( pAig );
|
||||
if ( p->pPars->fUpdateLevel )
|
||||
Aig_ManStartReverseLevels( pAig, 0 );
|
||||
// set elementary cuts for the PIs
|
||||
Dar_ManCutsStart( p );
|
||||
// resynthesize each node once
|
||||
clkStart = clock();
|
||||
p->nNodesInit = Aig_ManNodeNum(pAig);
|
||||
nNodesOld = Vec_PtrSize( pAig->vObjs );
|
||||
|
||||
pProgress = Extra_ProgressBarStart( stdout, nNodesOld );
|
||||
Aig_ManForEachObj( pAig, pObj, i )
|
||||
// pProgress = Extra_ProgressBarStart( stdout, 100 );
|
||||
// Aig_ManOrderStart( pAig );
|
||||
// Aig_ManForEachNodeInOrder( pAig, pObj )
|
||||
{
|
||||
// Extra_ProgressBarUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL );
|
||||
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
continue;
|
||||
if ( i > nNodesOld )
|
||||
break;
|
||||
|
||||
// consider freeing the cuts
|
||||
// if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 )
|
||||
// Dar_ManCutsStart( p );
|
||||
|
||||
// compute cuts for the node
|
||||
p->nNodesTried++;
|
||||
clk = clock();
|
||||
Dar_ObjComputeCuts_rec( p, pObj );
|
||||
p->timeCuts += clock() - clk;
|
||||
|
||||
// check if there is a trivial cut
|
||||
Dar_ObjForEachCut( pObj, pCut, k )
|
||||
if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) )
|
||||
break;
|
||||
if ( k < (int)pObj->nCuts )
|
||||
{
|
||||
assert( pCut->nLeaves < 2 );
|
||||
if ( pCut->nLeaves == 0 ) // replace by constant
|
||||
{
|
||||
assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF );
|
||||
pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 );
|
||||
pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 );
|
||||
}
|
||||
// remove the old cuts
|
||||
Dar_ObjSetCuts( pObj, NULL );
|
||||
// replace the node
|
||||
Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel );
|
||||
continue;
|
||||
}
|
||||
|
||||
// evaluate the cuts
|
||||
p->GainBest = -1;
|
||||
Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY;
|
||||
Dar_ObjForEachCut( pObj, pCut, k )
|
||||
Dar_LibEval( p, pObj, pCut, Required );
|
||||
// check the best gain
|
||||
if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) )
|
||||
{
|
||||
// Aig_ObjOrderAdvance( pAig );
|
||||
continue;
|
||||
}
|
||||
// remove the old cuts
|
||||
Dar_ObjSetCuts( pObj, NULL );
|
||||
// if we end up here, a rewriting step is accepted
|
||||
nNodeBefore = Aig_ManNodeNum( pAig );
|
||||
pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented!
|
||||
pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase );
|
||||
assert( (int)Aig_Regular(pObjNew)->Level <= Required );
|
||||
// replace the node
|
||||
Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel );
|
||||
// compare the gains
|
||||
nNodeAfter = Aig_ManNodeNum( pAig );
|
||||
assert( p->GainBest <= nNodeBefore - nNodeAfter );
|
||||
// count gains of this class
|
||||
p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter;
|
||||
}
|
||||
// Aig_ManOrderStop( pAig );
|
||||
|
||||
p->timeTotal = clock() - clkStart;
|
||||
p->timeOther = p->timeTotal - p->timeCuts - p->timeEval;
|
||||
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20);
|
||||
Dar_ManCutsFree( p );
|
||||
// put the nodes into the DFS order and reassign their IDs
|
||||
// Aig_NtkReassignIds( p );
|
||||
// fix the levels
|
||||
// Aig_ManVerifyLevel( pAig );
|
||||
if ( p->pPars->fFanout )
|
||||
Aig_ManFanoutStop( pAig );
|
||||
if ( p->pPars->fUpdateLevel )
|
||||
{
|
||||
// Aig_ManVerifyReverseLevel( pAig );
|
||||
Aig_ManStopReverseLevels( pAig );
|
||||
}
|
||||
// stop the rewriting manager
|
||||
Dar_ManStop( p );
|
||||
Aig_ManCheckPhase( pAig );
|
||||
// check
|
||||
if ( !Aig_ManCheck( pAig ) )
|
||||
{
|
||||
printf( "Aig_ManRewrite: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax )
|
||||
{
|
||||
Dar_Man_t * p;
|
||||
Dar_RwrPar_t Pars, * pPars = &Pars;
|
||||
Aig_Obj_t * pObj;
|
||||
Aig_MmFixed_t * pMemCuts;
|
||||
int i, nNodes, clk = 0, clkStart = clock();
|
||||
// remove dangling nodes
|
||||
if ( nNodes = Aig_ManCleanup( pAig ) )
|
||||
{
|
||||
// printf( "Removing %d nodes.\n", nNodes );
|
||||
}
|
||||
// create default parameters
|
||||
Dar_ManDefaultRwrParams( pPars );
|
||||
pPars->nCutsMax = nCutsMax;
|
||||
// create rewriting manager
|
||||
p = Dar_ManStart( pAig, pPars );
|
||||
// set elementary cuts for the PIs
|
||||
Dar_ManCutsStart( p );
|
||||
// compute cuts for each nodes in the topological order
|
||||
Aig_ManForEachNode( pAig, pObj, i )
|
||||
Dar_ObjComputeCuts( p, pObj );
|
||||
// free the cuts
|
||||
pMemCuts = p->pMemCuts;
|
||||
p->pMemCuts = NULL;
|
||||
// Dar_ManCutsFree( p );
|
||||
// stop the rewriting manager
|
||||
Dar_ManStop( p );
|
||||
return pMemCuts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,698 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darCut.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Computation of 4-input cuts.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of 1s in the machine word.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_WordCountOnes( unsigned uWord )
|
||||
{
|
||||
uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
|
||||
uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
|
||||
uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
|
||||
uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
|
||||
return (uWord & 0x0000FFFF) + (uWord>>16);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compute the cost of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutFindValue( Dar_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pLeaf;
|
||||
int i, Value, nOnes;
|
||||
assert( pCut->fUsed );
|
||||
Value = 0;
|
||||
nOnes = 0;
|
||||
Dar_CutForEachLeaf( p->pAig, pCut, pLeaf, i )
|
||||
{
|
||||
if ( pLeaf == NULL )
|
||||
return 0;
|
||||
assert( pLeaf != NULL );
|
||||
Value += pLeaf->nRefs;
|
||||
nOnes += (pLeaf->nRefs == 1);
|
||||
}
|
||||
if ( pCut->nLeaves < 2 )
|
||||
return 1001;
|
||||
// Value = Value * 100 / pCut->nLeaves;
|
||||
if ( Value > 1000 )
|
||||
Value = 1000;
|
||||
if ( nOnes > 3 )
|
||||
Value = 5 - nOnes;
|
||||
return Value;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the next free cut to use.]
|
||||
|
||||
Description [Uses the cut with the smallest value.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dar_Cut_t * Dar_CutFindFree( Dar_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Dar_Cut_t * pCut, * pCutMax;
|
||||
int i;
|
||||
pCutMax = NULL;
|
||||
Dar_ObjForEachCutAll( pObj, pCut, i )
|
||||
{
|
||||
if ( pCut->fUsed == 0 )
|
||||
return pCut;
|
||||
if ( pCut->nLeaves < 3 )
|
||||
continue;
|
||||
if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
|
||||
pCutMax = pCut;
|
||||
}
|
||||
if ( pCutMax == NULL )
|
||||
{
|
||||
Dar_ObjForEachCutAll( pObj, pCut, i )
|
||||
{
|
||||
if ( pCut->nLeaves < 2 )
|
||||
continue;
|
||||
if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
|
||||
pCutMax = pCut;
|
||||
}
|
||||
}
|
||||
if ( pCutMax == NULL )
|
||||
{
|
||||
Dar_ObjForEachCutAll( pObj, pCut, i )
|
||||
{
|
||||
if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
|
||||
pCutMax = pCut;
|
||||
}
|
||||
}
|
||||
assert( pCutMax != NULL );
|
||||
pCutMax->fUsed = 0;
|
||||
return pCutMax;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pDom is contained in pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutCheckDominance( Dar_Cut_t * pDom, Dar_Cut_t * pCut )
|
||||
{
|
||||
int i, k;
|
||||
assert( pDom->fUsed && pCut->fUsed );
|
||||
for ( i = 0; i < (int)pDom->nLeaves; i++ )
|
||||
{
|
||||
for ( k = 0; k < (int)pCut->nLeaves; k++ )
|
||||
if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
|
||||
break;
|
||||
if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
|
||||
return 0;
|
||||
}
|
||||
// every node in pDom is contained in pCut
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the cut is contained.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutFilter( Aig_Obj_t * pObj, Dar_Cut_t * pCut )
|
||||
{
|
||||
Dar_Cut_t * pTemp;
|
||||
int i;
|
||||
assert( pCut->fUsed );
|
||||
// go through the cuts of the node
|
||||
Dar_ObjForEachCut( pObj, pTemp, i )
|
||||
{
|
||||
if ( pTemp == pCut )
|
||||
continue;
|
||||
if ( pTemp->nLeaves > pCut->nLeaves )
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( Dar_CutCheckDominance( pCut, pTemp ) )
|
||||
{
|
||||
// remove contained cut
|
||||
pTemp->fUsed = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( Dar_CutCheckDominance( pTemp, pCut ) )
|
||||
{
|
||||
// remove the given cut
|
||||
pCut->fUsed = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutMergeOrdered( Dar_Cut_t * pC, Dar_Cut_t * pC0, Dar_Cut_t * pC1 )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
|
||||
// the case of the largest cut sizes
|
||||
if ( pC0->nLeaves == 4 && pC1->nLeaves == 4 )
|
||||
{
|
||||
if ( pC0->uSign != pC1->uSign )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == 4 )
|
||||
{
|
||||
if ( (pC0->uSign & pC1->uSign) != pC1->uSign )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pC1->nLeaves; i++ )
|
||||
{
|
||||
for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- )
|
||||
if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
|
||||
break;
|
||||
if ( k == -1 ) // did not find
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compare two cuts with different numbers
|
||||
i = k = 0;
|
||||
for ( c = 0; c < 4; c++ )
|
||||
{
|
||||
if ( k == (int)pC1->nLeaves )
|
||||
{
|
||||
if ( i == (int)pC0->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( i == (int)pC0->nLeaves )
|
||||
{
|
||||
if ( k == (int)pC1->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
k++;
|
||||
}
|
||||
if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves )
|
||||
return 0;
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutMerge( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1 )
|
||||
{
|
||||
assert( !pCut->fUsed );
|
||||
// merge the nodes
|
||||
if ( pCut0->nLeaves <= pCut1->nLeaves )
|
||||
{
|
||||
if ( !Dar_CutMergeOrdered( pCut, pCut1, pCut0 ) )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !Dar_CutMergeOrdered( pCut, pCut0, pCut1 ) )
|
||||
return 0;
|
||||
}
|
||||
pCut->uSign = pCut0->uSign | pCut1->uSign;
|
||||
pCut->fUsed = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dar_CutTruthPhase( Dar_Cut_t * pCut, Dar_Cut_t * pCut1 )
|
||||
{
|
||||
unsigned uPhase = 0;
|
||||
int i, k;
|
||||
for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
|
||||
{
|
||||
if ( k == (int)pCut1->nLeaves )
|
||||
break;
|
||||
if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
|
||||
continue;
|
||||
assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
|
||||
uPhase |= (1 << i);
|
||||
k++;
|
||||
}
|
||||
return uPhase;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Swaps two advancent variables of the truth table.]
|
||||
|
||||
Description [Swaps variable iVar and iVar+1.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dar_CutTruthSwapAdjacentVars( unsigned uTruth, int iVar )
|
||||
{
|
||||
assert( iVar >= 0 && iVar <= 2 );
|
||||
if ( iVar == 0 )
|
||||
return (uTruth & 0x99999999) | ((uTruth & 0x22222222) << 1) | ((uTruth & 0x44444444) >> 1);
|
||||
if ( iVar == 1 )
|
||||
return (uTruth & 0xC3C3C3C3) | ((uTruth & 0x0C0C0C0C) << 2) | ((uTruth & 0x30303030) >> 2);
|
||||
if ( iVar == 2 )
|
||||
return (uTruth & 0xF00FF00F) | ((uTruth & 0x00F000F0) << 4) | ((uTruth & 0x0F000F00) >> 4);
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Expands the truth table according to the phase.]
|
||||
|
||||
Description [The input and output truth tables are in pIn/pOut. The current number
|
||||
of variables is nVars. The total number of variables in nVarsAll. The last argument
|
||||
(Phase) contains shows where the variables should go.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dar_CutTruthStretch( unsigned uTruth, int nVars, unsigned Phase )
|
||||
{
|
||||
int i, k, Var = nVars - 1;
|
||||
for ( i = 3; i >= 0; i-- )
|
||||
if ( Phase & (1 << i) )
|
||||
{
|
||||
for ( k = Var; k < i; k++ )
|
||||
uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k );
|
||||
Var--;
|
||||
}
|
||||
assert( Var == -1 );
|
||||
return uTruth;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Shrinks the truth table according to the phase.]
|
||||
|
||||
Description [The input and output truth tables are in pIn/pOut. The current number
|
||||
of variables is nVars. The total number of variables in nVarsAll. The last argument
|
||||
(Phase) contains shows what variables should remain.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dar_CutTruthShrink( unsigned uTruth, int nVars, unsigned Phase )
|
||||
{
|
||||
int i, k, Var = 0;
|
||||
for ( i = 0; i < 4; i++ )
|
||||
if ( Phase & (1 << i) )
|
||||
{
|
||||
for ( k = i-1; k >= Var; k-- )
|
||||
uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k );
|
||||
Var++;
|
||||
}
|
||||
return uTruth;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs truth table computation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dar_CutTruth( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1, int fCompl0, int fCompl1 )
|
||||
{
|
||||
unsigned uTruth0 = fCompl0 ? ~pCut0->uTruth : pCut0->uTruth;
|
||||
unsigned uTruth1 = fCompl1 ? ~pCut1->uTruth : pCut1->uTruth;
|
||||
uTruth0 = Dar_CutTruthStretch( uTruth0, pCut0->nLeaves, Dar_CutTruthPhase(pCut, pCut0) );
|
||||
uTruth1 = Dar_CutTruthStretch( uTruth1, pCut1->nLeaves, Dar_CutTruthPhase(pCut, pCut1) );
|
||||
return uTruth0 & uTruth1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Minimize support of the cut.]
|
||||
|
||||
Description [Returns 1 if the node's support has changed]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dar_CutSuppMinimize( Dar_Cut_t * pCut )
|
||||
{
|
||||
unsigned uMasks[4][2] = {
|
||||
{ 0x5555, 0xAAAA },
|
||||
{ 0x3333, 0xCCCC },
|
||||
{ 0x0F0F, 0xF0F0 },
|
||||
{ 0x00FF, 0xFF00 }
|
||||
};
|
||||
unsigned uPhase = 0, uTruth = 0xFFFF & pCut->uTruth;
|
||||
int i, k, nLeaves;
|
||||
assert( pCut->fUsed );
|
||||
// compute the truth support of the cut's function
|
||||
nLeaves = pCut->nLeaves;
|
||||
for ( i = 0; i < (int)pCut->nLeaves; i++ )
|
||||
if ( (uTruth & uMasks[i][0]) == ((uTruth & uMasks[i][1]) >> (1 << i)) )
|
||||
nLeaves--;
|
||||
else
|
||||
uPhase |= (1 << i);
|
||||
if ( nLeaves == (int)pCut->nLeaves )
|
||||
return 0;
|
||||
// shrink the truth table
|
||||
uTruth = Dar_CutTruthShrink( uTruth, pCut->nLeaves, uPhase );
|
||||
pCut->uTruth = 0xFFFF & uTruth;
|
||||
// update leaves and signature
|
||||
pCut->uSign = 0;
|
||||
for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
|
||||
{
|
||||
if ( !(uPhase & (1 << i)) )
|
||||
continue;
|
||||
pCut->pLeaves[k++] = pCut->pLeaves[i];
|
||||
pCut->uSign |= Aig_ObjCutSign( pCut->pLeaves[i] );
|
||||
}
|
||||
assert( k == nLeaves );
|
||||
pCut->nLeaves = nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManCutsFree( Dar_Man_t * p )
|
||||
{
|
||||
if ( p->pMemCuts == NULL )
|
||||
return;
|
||||
Aig_MmFixedStop( p->pMemCuts, 0 );
|
||||
p->pMemCuts = NULL;
|
||||
// Aig_ManCleanData( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Dar_Cut_t * pCutSet, * pCut;
|
||||
int i;
|
||||
assert( Dar_ObjCuts(pObj) == NULL );
|
||||
pObj->nCuts = p->pPars->nCutsMax;
|
||||
// create the cutset of the node
|
||||
pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
|
||||
Dar_ObjSetCuts( pObj, pCutSet );
|
||||
Dar_ObjForEachCut( pObj, pCut, i )
|
||||
pCut->fUsed = 0;
|
||||
// add unit cut if needed
|
||||
pCut = pCutSet;
|
||||
pCut->fUsed = 1;
|
||||
if ( Aig_ObjIsConst1(pObj) )
|
||||
{
|
||||
pCut->nLeaves = 0;
|
||||
pCut->uSign = 0;
|
||||
pCut->uTruth = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCut->nLeaves = 1;
|
||||
pCut->pLeaves[0] = pObj->Id;
|
||||
pCut->uSign = Aig_ObjCutSign( pObj->Id );
|
||||
pCut->uTruth = 0xAAAA;
|
||||
}
|
||||
pCut->Value = Dar_CutFindValue( p, pCut );
|
||||
return pCutSet;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManCutsStart( Dar_Man_t * p )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Aig_ManCleanData( p->pAig );
|
||||
Aig_MmFixedRestart( p->pMemCuts );
|
||||
Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) );
|
||||
Aig_ManForEachPi( p->pAig, pObj, i )
|
||||
Dar_ObjPrepareCuts( p, pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
|
||||
Aig_Obj_t * pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
|
||||
Aig_Obj_t * pFaninR0 = Aig_Regular(pFanin0);
|
||||
Aig_Obj_t * pFaninR1 = Aig_Regular(pFanin1);
|
||||
Dar_Cut_t * pCutSet, * pCut0, * pCut1, * pCut;
|
||||
int i, k, RetValue;
|
||||
|
||||
assert( !Aig_IsComplement(pObj) );
|
||||
assert( Aig_ObjIsNode(pObj) );
|
||||
assert( Dar_ObjCuts(pObj) == NULL );
|
||||
assert( Dar_ObjCuts(pFaninR0) != NULL );
|
||||
assert( Dar_ObjCuts(pFaninR1) != NULL );
|
||||
|
||||
// set up the first cut
|
||||
pCutSet = Dar_ObjPrepareCuts( p, pObj );
|
||||
// make sure fanins cuts are computed
|
||||
Dar_ObjForEachCut( pFaninR0, pCut0, i )
|
||||
Dar_ObjForEachCut( pFaninR1, pCut1, k )
|
||||
{
|
||||
p->nCutsAll++;
|
||||
// make sure K-feasible cut exists
|
||||
if ( Dar_WordCountOnes(pCut0->uSign | pCut1->uSign) > 4 )
|
||||
continue;
|
||||
// get the next cut of this node
|
||||
pCut = Dar_CutFindFree( p, pObj );
|
||||
// create the new cut
|
||||
if ( !Dar_CutMerge( pCut, pCut0, pCut1 ) )
|
||||
{
|
||||
assert( !pCut->fUsed );
|
||||
continue;
|
||||
}
|
||||
p->nCutsTried++;
|
||||
// check dominance
|
||||
if ( Dar_CutFilter( pObj, pCut ) )
|
||||
{
|
||||
assert( !pCut->fUsed );
|
||||
continue;
|
||||
}
|
||||
// compute truth table
|
||||
pCut->uTruth = 0xFFFF & Dar_CutTruth( pCut, pCut0, pCut1, Aig_IsComplement(pFanin0), Aig_IsComplement(pFanin1) );
|
||||
|
||||
// minimize support of the cut
|
||||
if ( Dar_CutSuppMinimize( pCut ) )
|
||||
{
|
||||
RetValue = Dar_CutFilter( pObj, pCut );
|
||||
assert( !RetValue );
|
||||
}
|
||||
|
||||
// assign the value of the cut
|
||||
pCut->Value = Dar_CutFindValue( p, pCut );
|
||||
// if the cut contains removed node, do not use it
|
||||
if ( pCut->Value == 0 )
|
||||
{
|
||||
p->nCutsSkipped++;
|
||||
pCut->fUsed = 0;
|
||||
}
|
||||
else if ( pCut->nLeaves < 2 )
|
||||
return pCutSet;
|
||||
}
|
||||
// count the number of nontrivial cuts cuts
|
||||
Dar_ObjForEachCut( pObj, pCut, i )
|
||||
p->nCutsUsed += pCut->fUsed;
|
||||
// discount trivial cut
|
||||
p->nCutsUsed--;
|
||||
return pCutSet;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj )
|
||||
{
|
||||
if ( Dar_ObjCuts(pObj) )
|
||||
return Dar_ObjCuts(pObj);
|
||||
if ( Aig_ObjIsBuf(pObj) )
|
||||
return Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) );
|
||||
Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) );
|
||||
Dar_ObjComputeCuts_rec( p, Aig_ObjFanin1(pObj) );
|
||||
return Dar_ObjComputeCuts( p, pObj );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,161 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darInt.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Internal declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __DAR_INT_H__
|
||||
#define __DAR_INT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "vec.h"
|
||||
#include "aig.h"
|
||||
#include "dar.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Dar_Man_t_ Dar_Man_t;
|
||||
typedef struct Dar_Cut_t_ Dar_Cut_t;
|
||||
|
||||
// the AIG 4-cut
|
||||
struct Dar_Cut_t_ // 6 words
|
||||
{
|
||||
unsigned uSign; // cut signature
|
||||
unsigned uTruth : 16; // the truth table of the cut function
|
||||
unsigned Value : 11; // the value of the cut
|
||||
unsigned fBest : 1; // marks the best cut
|
||||
unsigned fUsed : 1; // marks the cut currently in use
|
||||
unsigned nLeaves : 3; // the number of leaves
|
||||
int pLeaves[4]; // the array of leaves
|
||||
};
|
||||
|
||||
// the AIG manager
|
||||
struct Dar_Man_t_
|
||||
{
|
||||
// input data
|
||||
Dar_RwrPar_t * pPars; // rewriting parameters
|
||||
Aig_Man_t * pAig; // AIG manager
|
||||
// various data members
|
||||
Aig_MmFixed_t * pMemCuts; // memory manager for cuts
|
||||
void * pManCnf; // CNF managers
|
||||
// current rewriting step
|
||||
Vec_Ptr_t * vLeavesBest; // the best set of leaves
|
||||
int OutBest; // the best output (in the library)
|
||||
int OutNumBest; // the best number of the output
|
||||
int GainBest; // the best gain
|
||||
int LevelBest; // the level of node with the best gain
|
||||
int ClassBest; // the equivalence class of the best replacement
|
||||
// function statistics
|
||||
int nTotalSubgs; // the total number of subgraphs tried
|
||||
int ClassTimes[222];// the runtimes for each class
|
||||
int ClassGains[222];// the gains for each class
|
||||
int ClassSubgs[222];// the graphs for each class
|
||||
int nCutMemUsed; // memory used for cuts
|
||||
// rewriting statistics
|
||||
int nNodesInit; // the original number of nodes
|
||||
int nNodesTried; // the number of nodes attempted
|
||||
int nCutsAll; // all cut pairs
|
||||
int nCutsTried; // computed cuts
|
||||
int nCutsUsed; // used cuts
|
||||
int nCutsBad; // bad cuts due to absent fanin
|
||||
int nCutsGood; // good cuts
|
||||
int nCutsSkipped; // skipped bad cuts
|
||||
// timing statistics
|
||||
int timeCuts;
|
||||
int timeEval;
|
||||
int timeOther;
|
||||
int timeTotal;
|
||||
int time1;
|
||||
int time2;
|
||||
};
|
||||
|
||||
static inline Dar_Cut_t * Dar_ObjCuts( Aig_Obj_t * pObj ) { return pObj->pData; }
|
||||
static inline void Dar_ObjSetCuts( Aig_Obj_t * pObj, Dar_Cut_t * pCuts ) { assert( !Aig_ObjIsNone(pObj) ); pObj->pData = pCuts; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// iterator over all cuts of the node
|
||||
#define Dar_ObjForEachCutAll( pObj, pCut, i ) \
|
||||
for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ )
|
||||
#define Dar_ObjForEachCut( pObj, pCut, i ) \
|
||||
for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) if ( (pCut)->fUsed==0 ) {} else
|
||||
// iterator over leaves of the cut
|
||||
#define Dar_CutForEachLeaf( p, pCut, pLeaf, i ) \
|
||||
for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pLeaf) = Aig_ManObj(p, (pCut)->pLeaves[i])), 1); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== darBalance.c ========================================================*/
|
||||
/*=== darCore.c ===========================================================*/
|
||||
/*=== darCut.c ============================================================*/
|
||||
extern void Dar_ManCutsStart( Dar_Man_t * p );
|
||||
extern void Dar_ManCutsFree( Dar_Man_t * p );
|
||||
extern Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj );
|
||||
extern Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj );
|
||||
/*=== darData.c ===========================================================*/
|
||||
extern Vec_Int_t * Dar_LibReadNodes();
|
||||
extern Vec_Int_t * Dar_LibReadOuts();
|
||||
extern Vec_Int_t * Dar_LibReadPrios();
|
||||
/*=== darLib.c ============================================================*/
|
||||
extern void Dar_LibStart();
|
||||
extern void Dar_LibStop();
|
||||
extern void Dar_LibPrepare( int nSubgraphs );
|
||||
extern void Dar_LibReturnCanonicals( unsigned * pCanons );
|
||||
extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required );
|
||||
extern Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p );
|
||||
/*=== darMan.c ============================================================*/
|
||||
extern Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars );
|
||||
extern void Dar_ManStop( Dar_Man_t * p );
|
||||
extern void Dar_ManPrintStats( Dar_Man_t * p );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,980 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darLib.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Library of AIG subgraphs used for rewriting.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darLib.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Dar_Lib_t_ Dar_Lib_t;
|
||||
typedef struct Dar_LibObj_t_ Dar_LibObj_t;
|
||||
typedef struct Dar_LibDat_t_ Dar_LibDat_t;
|
||||
|
||||
struct Dar_LibObj_t_ // library object (2 words)
|
||||
{
|
||||
unsigned Fan0 : 16; // the first fanin
|
||||
unsigned Fan1 : 16; // the second fanin
|
||||
unsigned fCompl0 : 1; // the first compl attribute
|
||||
unsigned fCompl1 : 1; // the second compl attribute
|
||||
unsigned fPhase : 1; // the phase of the node
|
||||
unsigned fTerm : 1; // indicates a PI
|
||||
unsigned Num : 28; // internal use
|
||||
};
|
||||
|
||||
struct Dar_LibDat_t_ // library object data
|
||||
{
|
||||
Aig_Obj_t * pFunc; // the corresponding AIG node if it exists
|
||||
int Level; // level of this node after it is constructured
|
||||
int TravId; // traversal ID of the library object data
|
||||
unsigned char fMffc; // set to one if node is part of MFFC
|
||||
unsigned char nLats[3]; // the number of latches on the input/output stem
|
||||
};
|
||||
|
||||
struct Dar_Lib_t_ // library
|
||||
{
|
||||
// objects
|
||||
Dar_LibObj_t * pObjs; // the set of library objects
|
||||
int nObjs; // the number of objects used
|
||||
int iObj; // the current object
|
||||
// structures by class
|
||||
int nSubgr[222]; // the number of subgraphs by class
|
||||
int * pSubgr[222]; // the subgraphs for each class
|
||||
int * pSubgrMem; // memory for subgraph pointers
|
||||
int nSubgrTotal; // the total number of subgraph
|
||||
// structure priorities
|
||||
int * pPriosMem; // memory for priority of structures
|
||||
int * pPrios[222]; // pointers to the priority numbers
|
||||
// structure places in the priorities
|
||||
int * pPlaceMem; // memory for places of structures in the priority lists
|
||||
int * pPlace[222]; // pointers to the places numbers
|
||||
// structure scores
|
||||
int * pScoreMem; // memory for scores of structures
|
||||
int * pScore[222]; // pointers to the scores numbers
|
||||
// nodes by class
|
||||
int nNodes[222]; // the number of nodes by class
|
||||
int * pNodes[222]; // the nodes for each class
|
||||
int * pNodesMem; // memory for nodes pointers
|
||||
int nNodesTotal; // the total number of nodes
|
||||
// prepared library
|
||||
int nSubgraphs;
|
||||
int nNodes0Max;
|
||||
// nodes by class
|
||||
int nNodes0[222]; // the number of nodes by class
|
||||
int * pNodes0[222]; // the nodes for each class
|
||||
int * pNodes0Mem; // memory for nodes pointers
|
||||
int nNodes0Total; // the total number of nodes
|
||||
// structures by class
|
||||
int nSubgr0[222]; // the number of subgraphs by class
|
||||
int * pSubgr0[222]; // the subgraphs for each class
|
||||
int * pSubgr0Mem; // memory for subgraph pointers
|
||||
int nSubgr0Total; // the total number of subgraph
|
||||
// object data
|
||||
Dar_LibDat_t * pDatas;
|
||||
int nDatas;
|
||||
// information about NPN classes
|
||||
char ** pPerms4;
|
||||
unsigned short * puCanons;
|
||||
char * pPhases;
|
||||
char * pPerms;
|
||||
unsigned char * pMap;
|
||||
};
|
||||
|
||||
static Dar_Lib_t * s_DarLib = NULL;
|
||||
|
||||
static inline Dar_LibObj_t * Dar_LibObj( Dar_Lib_t * p, int Id ) { return p->pObjs + Id; }
|
||||
static inline int Dar_LibObjTruth( Dar_LibObj_t * pObj ) { return pObj->Num < (0xFFFF & ~pObj->Num) ? pObj->Num : (0xFFFF & ~pObj->Num); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Lib_t * Dar_LibAlloc( int nObjs )
|
||||
{
|
||||
unsigned uTruths[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
|
||||
Dar_Lib_t * p;
|
||||
int i, clk = clock();
|
||||
p = ALLOC( Dar_Lib_t, 1 );
|
||||
memset( p, 0, sizeof(Dar_Lib_t) );
|
||||
// allocate objects
|
||||
p->nObjs = nObjs;
|
||||
p->pObjs = ALLOC( Dar_LibObj_t, nObjs );
|
||||
memset( p->pObjs, 0, sizeof(Dar_LibObj_t) * nObjs );
|
||||
// allocate canonical data
|
||||
p->pPerms4 = Extra_Permutations( 4 );
|
||||
Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap );
|
||||
// start the elementary objects
|
||||
p->iObj = 4;
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
p->pObjs[i].fTerm = 1;
|
||||
p->pObjs[i].Num = uTruths[i];
|
||||
}
|
||||
// PRT( "Library start", clock() - clk );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Frees the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibFree( Dar_Lib_t * p )
|
||||
{
|
||||
free( p->pObjs );
|
||||
free( p->pDatas );
|
||||
free( p->pNodesMem );
|
||||
free( p->pNodes0Mem );
|
||||
free( p->pSubgrMem );
|
||||
free( p->pSubgr0Mem );
|
||||
free( p->pPriosMem );
|
||||
FREE( p->pPlaceMem );
|
||||
FREE( p->pScoreMem );
|
||||
free( p->pPerms4 );
|
||||
free( p->puCanons );
|
||||
free( p->pPhases );
|
||||
free( p->pPerms );
|
||||
free( p->pMap );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns canonical truth tables.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibReturnCanonicals( unsigned * pCanons )
|
||||
{
|
||||
int Visits[222] = {0};
|
||||
int i, k;
|
||||
// find canonical truth tables
|
||||
for ( i = k = 0; i < (1<<16); i++ )
|
||||
if ( !Visits[s_DarLib->pMap[i]] )
|
||||
{
|
||||
Visits[s_DarLib->pMap[i]] = 1;
|
||||
pCanons[k++] = ((i<<16) | i);
|
||||
}
|
||||
assert( k == 222 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds one AND to the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibAddNode( Dar_Lib_t * p, int Id0, int Id1, int fCompl0, int fCompl1 )
|
||||
{
|
||||
Dar_LibObj_t * pFan0 = Dar_LibObj( p, Id0 );
|
||||
Dar_LibObj_t * pFan1 = Dar_LibObj( p, Id1 );
|
||||
Dar_LibObj_t * pObj = p->pObjs + p->iObj++;
|
||||
pObj->Fan0 = Id0;
|
||||
pObj->Fan1 = Id1;
|
||||
pObj->fCompl0 = fCompl0;
|
||||
pObj->fCompl1 = fCompl1;
|
||||
pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase);
|
||||
pObj->Num = 0xFFFF & (fCompl0? ~pFan0->Num : pFan0->Num) & (fCompl1? ~pFan1->Num : pFan1->Num);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds one AND to the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibSetup_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect )
|
||||
{
|
||||
if ( pObj->fTerm || (int)pObj->Num == Class )
|
||||
return;
|
||||
pObj->Num = Class;
|
||||
Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect );
|
||||
Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect );
|
||||
if ( fCollect )
|
||||
p->pNodes[Class][ p->nNodes[Class]++ ] = pObj-p->pObjs;
|
||||
else
|
||||
p->nNodes[Class]++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds one AND to the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibSetup( Dar_Lib_t * p, Vec_Int_t * vOuts, Vec_Int_t * vPrios )
|
||||
{
|
||||
int fTraining = 0;
|
||||
Dar_LibObj_t * pObj;
|
||||
int nNodesTotal, uTruth, Class, Out, i, k;
|
||||
assert( p->iObj == p->nObjs );
|
||||
|
||||
// count the number of representatives of each class
|
||||
for ( i = 0; i < 222; i++ )
|
||||
p->nSubgr[i] = p->nNodes[i] = 0;
|
||||
Vec_IntForEachEntry( vOuts, Out, i )
|
||||
{
|
||||
pObj = Dar_LibObj( p, Out );
|
||||
uTruth = Dar_LibObjTruth( pObj );
|
||||
Class = p->pMap[uTruth];
|
||||
p->nSubgr[Class]++;
|
||||
}
|
||||
// allocate memory for the roots of each class
|
||||
p->pSubgrMem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->pSubgr0Mem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->nSubgrTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pSubgr[i] = p->pSubgrMem + p->nSubgrTotal;
|
||||
p->pSubgr0[i] = p->pSubgr0Mem + p->nSubgrTotal;
|
||||
p->nSubgrTotal += p->nSubgr[i];
|
||||
p->nSubgr[i] = 0;
|
||||
}
|
||||
assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
|
||||
// add the outputs to storage
|
||||
Vec_IntForEachEntry( vOuts, Out, i )
|
||||
{
|
||||
pObj = Dar_LibObj( p, Out );
|
||||
uTruth = Dar_LibObjTruth( pObj );
|
||||
Class = p->pMap[uTruth];
|
||||
p->pSubgr[Class][ p->nSubgr[Class]++ ] = Out;
|
||||
}
|
||||
|
||||
if ( fTraining )
|
||||
{
|
||||
// allocate memory for the priority of roots of each class
|
||||
p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->nSubgrTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pPrios[i] = p->pPriosMem + p->nSubgrTotal;
|
||||
p->nSubgrTotal += p->nSubgr[i];
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
p->pPrios[i][k] = k;
|
||||
|
||||
}
|
||||
assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
|
||||
|
||||
// allocate memory for the priority of roots of each class
|
||||
p->pPlaceMem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->nSubgrTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pPlace[i] = p->pPlaceMem + p->nSubgrTotal;
|
||||
p->nSubgrTotal += p->nSubgr[i];
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
p->pPlace[i][k] = k;
|
||||
|
||||
}
|
||||
assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
|
||||
|
||||
// allocate memory for the priority of roots of each class
|
||||
p->pScoreMem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->nSubgrTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pScore[i] = p->pScoreMem + p->nSubgrTotal;
|
||||
p->nSubgrTotal += p->nSubgr[i];
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
p->pScore[i][k] = 0;
|
||||
|
||||
}
|
||||
assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int Counter = 0;
|
||||
// allocate memory for the priority of roots of each class
|
||||
p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) );
|
||||
p->nSubgrTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pPrios[i] = p->pPriosMem + p->nSubgrTotal;
|
||||
p->nSubgrTotal += p->nSubgr[i];
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
p->pPrios[i][k] = Vec_IntEntry(vPrios, Counter++);
|
||||
|
||||
}
|
||||
assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
|
||||
assert( Counter == Vec_IntSize(vPrios) );
|
||||
}
|
||||
|
||||
// create traversal IDs
|
||||
for ( i = 0; i < p->iObj; i++ )
|
||||
Dar_LibObj(p, i)->Num = 0xff;
|
||||
// count nodes in each class
|
||||
for ( i = 0; i < 222; i++ )
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 0 );
|
||||
// count the total number of nodes
|
||||
p->nNodesTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
p->nNodesTotal += p->nNodes[i];
|
||||
// allocate memory for the nodes of each class
|
||||
p->pNodesMem = ALLOC( int, p->nNodesTotal );
|
||||
p->pNodes0Mem = ALLOC( int, p->nNodesTotal );
|
||||
p->nNodesTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
p->pNodes[i] = p->pNodesMem + p->nNodesTotal;
|
||||
p->pNodes0[i] = p->pNodes0Mem + p->nNodesTotal;
|
||||
p->nNodesTotal += p->nNodes[i];
|
||||
p->nNodes[i] = 0;
|
||||
}
|
||||
// create traversal IDs
|
||||
for ( i = 0; i < p->iObj; i++ )
|
||||
Dar_LibObj(p, i)->Num = 0xff;
|
||||
// add the nodes to storage
|
||||
nNodesTotal = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
for ( k = 0; k < p->nSubgr[i]; k++ )
|
||||
Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 1 );
|
||||
nNodesTotal += p->nNodes[i];
|
||||
//printf( "Class %3d : Subgraphs = %4d. Nodes = %5d.\n", i, p->nSubgr[i], p->nNodes[i] );
|
||||
}
|
||||
assert( nNodesTotal == p->nNodesTotal );
|
||||
// prepare the number of the PI nodes
|
||||
for ( i = 0; i < 4; i++ )
|
||||
Dar_LibObj(p, i)->Num = i;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibCreateData( Dar_Lib_t * p, int nDatas )
|
||||
{
|
||||
if ( p->nDatas == nDatas )
|
||||
return;
|
||||
FREE( p->pDatas );
|
||||
// allocate datas
|
||||
p->nDatas = nDatas;
|
||||
p->pDatas = ALLOC( Dar_LibDat_t, nDatas );
|
||||
memset( p->pDatas, 0, sizeof(Dar_LibDat_t) * nDatas );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Adds one AND to the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibSetup0_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect )
|
||||
{
|
||||
if ( pObj->fTerm || (int)pObj->Num == Class )
|
||||
return;
|
||||
pObj->Num = Class;
|
||||
Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect );
|
||||
Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect );
|
||||
if ( fCollect )
|
||||
p->pNodes0[Class][ p->nNodes0[Class]++ ] = pObj-p->pObjs;
|
||||
else
|
||||
p->nNodes0[Class]++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibPrepare( int nSubgraphs )
|
||||
{
|
||||
Dar_Lib_t * p = s_DarLib;
|
||||
int i, k, nNodes0Total;
|
||||
if ( p->nSubgraphs == nSubgraphs )
|
||||
return;
|
||||
|
||||
// favor special classes:
|
||||
// 1 : F = (!d*!c*!b*!a)
|
||||
// 4 : F = (!d*!c*!(b*a))
|
||||
// 12 : F = (!d*!(c*!(!b*!a)))
|
||||
// 20 : F = (!d*!(c*b*a))
|
||||
|
||||
// set the subgraph counters
|
||||
p->nSubgr0Total = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
// if ( i == 1 || i == 4 || i == 12 || i == 20 ) // special classes
|
||||
if ( i == 1 ) // special classes
|
||||
p->nSubgr0[i] = p->nSubgr[i];
|
||||
else
|
||||
p->nSubgr0[i] = AIG_MIN( p->nSubgr[i], nSubgraphs );
|
||||
p->nSubgr0Total += p->nSubgr0[i];
|
||||
for ( k = 0; k < p->nSubgr0[i]; k++ )
|
||||
p->pSubgr0[i][k] = p->pSubgr[i][ p->pPrios[i][k] ];
|
||||
}
|
||||
|
||||
// count the number of nodes
|
||||
// clean node counters
|
||||
for ( i = 0; i < 222; i++ )
|
||||
p->nNodes0[i] = 0;
|
||||
// create traversal IDs
|
||||
for ( i = 0; i < p->iObj; i++ )
|
||||
Dar_LibObj(p, i)->Num = 0xff;
|
||||
// count nodes in each class
|
||||
// count the total number of nodes and the largest class
|
||||
p->nNodes0Total = 0;
|
||||
p->nNodes0Max = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
for ( k = 0; k < p->nSubgr0[i]; k++ )
|
||||
Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 0 );
|
||||
p->nNodes0Total += p->nNodes0[i];
|
||||
p->nNodes0Max = AIG_MAX( p->nNodes0Max, p->nNodes0[i] );
|
||||
}
|
||||
|
||||
// clean node counters
|
||||
for ( i = 0; i < 222; i++ )
|
||||
p->nNodes0[i] = 0;
|
||||
// create traversal IDs
|
||||
for ( i = 0; i < p->iObj; i++ )
|
||||
Dar_LibObj(p, i)->Num = 0xff;
|
||||
// add the nodes to storage
|
||||
nNodes0Total = 0;
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
for ( k = 0; k < p->nSubgr0[i]; k++ )
|
||||
Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 1 );
|
||||
nNodes0Total += p->nNodes0[i];
|
||||
}
|
||||
assert( nNodes0Total == p->nNodes0Total );
|
||||
// prepare the number of the PI nodes
|
||||
for ( i = 0; i < 4; i++ )
|
||||
Dar_LibObj(p, i)->Num = i;
|
||||
|
||||
// realloc the datas
|
||||
Dar_LibCreateData( p, p->nNodes0Max + 32 );
|
||||
// allocated more because Dar_LibBuildBest() sometimes requires more entries
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reads library from array.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Lib_t * Dar_LibRead()
|
||||
{
|
||||
Vec_Int_t * vObjs, * vOuts, * vPrios;
|
||||
Dar_Lib_t * p;
|
||||
int i;
|
||||
// read nodes and outputs
|
||||
vObjs = Dar_LibReadNodes();
|
||||
vOuts = Dar_LibReadOuts();
|
||||
vPrios = Dar_LibReadPrios();
|
||||
// create library
|
||||
p = Dar_LibAlloc( Vec_IntSize(vObjs)/2 + 4 );
|
||||
// create nodes
|
||||
for ( i = 0; i < vObjs->nSize; i += 2 )
|
||||
Dar_LibAddNode( p, vObjs->pArray[i] >> 1, vObjs->pArray[i+1] >> 1,
|
||||
vObjs->pArray[i] & 1, vObjs->pArray[i+1] & 1 );
|
||||
// create outputs
|
||||
Dar_LibSetup( p, vOuts, vPrios );
|
||||
Vec_IntFree( vObjs );
|
||||
Vec_IntFree( vOuts );
|
||||
Vec_IntFree( vPrios );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibStart()
|
||||
{
|
||||
int clk = clock();
|
||||
assert( s_DarLib == NULL );
|
||||
s_DarLib = Dar_LibRead();
|
||||
printf( "The 4-input library started with %d nodes and %d subgraphs. ", s_DarLib->nObjs - 4, s_DarLib->nSubgrTotal );
|
||||
PRT( "Time", clock() - clk );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibStop()
|
||||
{
|
||||
assert( s_DarLib != NULL );
|
||||
Dar_LibFree( s_DarLib );
|
||||
s_DarLib = NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Updates the score of the class and adjusts the priority of this class.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibIncrementScore( int Class, int Out, int Gain )
|
||||
{
|
||||
int * pPrios = s_DarLib->pPrios[Class]; // pPrios[i] = Out
|
||||
int * pPlace = s_DarLib->pPlace[Class]; // pPlace[Out] = i
|
||||
int * pScore = s_DarLib->pScore[Class]; // score of Out
|
||||
int Out2;
|
||||
assert( Class >= 0 && Class < 222 );
|
||||
assert( Out >= 0 && Out < s_DarLib->nSubgr[Class] );
|
||||
assert( pPlace[pPrios[Out]] == Out );
|
||||
// increment the score
|
||||
pScore[Out] += Gain;
|
||||
// move the out in the order
|
||||
while ( pPlace[Out] > 0 && pScore[Out] > pScore[ pPrios[pPlace[Out]-1] ] )
|
||||
{
|
||||
// get the previous output in the priority list
|
||||
Out2 = pPrios[pPlace[Out]-1];
|
||||
// swap Out and Out2
|
||||
pPlace[Out]--;
|
||||
pPlace[Out2]++;
|
||||
pPrios[pPlace[Out]] = Out;
|
||||
pPrios[pPlace[Out2]] = Out2;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints out the priorities into the file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibDumpPriorities()
|
||||
{
|
||||
int i, k, Out, Out2, Counter = 0, Printed = 0;
|
||||
printf( "\nOutput priorities (total = %d):\n", s_DarLib->nSubgrTotal );
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
// printf( "Class%d: ", i );
|
||||
for ( k = 0; k < s_DarLib->nSubgr[i]; k++ )
|
||||
{
|
||||
Out = s_DarLib->pPrios[i][k];
|
||||
Out2 = k == 0 ? Out : s_DarLib->pPrios[i][k-1];
|
||||
assert( s_DarLib->pScore[i][Out2] >= s_DarLib->pScore[i][Out] );
|
||||
// printf( "%d(%d), ", Out, s_DarLib->pScore[i][Out] );
|
||||
printf( "%d, ", Out );
|
||||
Printed++;
|
||||
if ( ++Counter == 15 )
|
||||
{
|
||||
printf( "\n" );
|
||||
Counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf( "\n" );
|
||||
assert( Printed == s_DarLib->nSubgrTotal );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Matches the cut with its canonical form.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut )
|
||||
{
|
||||
Aig_Obj_t * pFanin;
|
||||
unsigned uPhase;
|
||||
char * pPerm;
|
||||
int i;
|
||||
assert( pCut->nLeaves == 4 );
|
||||
// get the fanin permutation
|
||||
uPhase = s_DarLib->pPhases[pCut->uTruth];
|
||||
pPerm = s_DarLib->pPerms4[ s_DarLib->pPerms[pCut->uTruth] ];
|
||||
// collect fanins with the corresponding permutation/phase
|
||||
for ( i = 0; i < (int)pCut->nLeaves; i++ )
|
||||
{
|
||||
pFanin = Aig_ManObj( p->pAig, pCut->pLeaves[pPerm[i]] );
|
||||
if ( pFanin == NULL )
|
||||
{
|
||||
p->nCutsBad++;
|
||||
return 0;
|
||||
}
|
||||
pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) );
|
||||
s_DarLib->pDatas[i].pFunc = pFanin;
|
||||
s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level;
|
||||
}
|
||||
p->nCutsGood++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Marks the MFFC of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves )
|
||||
{
|
||||
int i, nNodes;
|
||||
// mark the cut leaves
|
||||
for ( i = 0; i < nLeaves; i++ )
|
||||
Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++;
|
||||
// label MFFC with current ID
|
||||
nNodes = Aig_NodeMffsLabel( p, pRoot );
|
||||
// unmark the cut leaves
|
||||
for ( i = 0; i < nLeaves; i++ )
|
||||
Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--;
|
||||
return nNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluates one cut.]
|
||||
|
||||
Description [Returns the best gain.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibObjPrint_rec( Dar_LibObj_t * pObj )
|
||||
{
|
||||
if ( pObj->fTerm )
|
||||
{
|
||||
printf( "%c", 'a' + pObj - s_DarLib->pObjs );
|
||||
return;
|
||||
}
|
||||
printf( "(" );
|
||||
Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan0) );
|
||||
if ( pObj->fCompl0 )
|
||||
printf( "\'" );
|
||||
Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan1) );
|
||||
if ( pObj->fCompl0 )
|
||||
printf( "\'" );
|
||||
printf( ")" );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Assigns numbers to the nodes of one class.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class )
|
||||
{
|
||||
Dar_LibObj_t * pObj;
|
||||
Dar_LibDat_t * pData, * pData0, * pData1;
|
||||
Aig_Obj_t * pFanin0, * pFanin1;
|
||||
int i;
|
||||
for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ )
|
||||
{
|
||||
// get one class node, assign its temporary number and set its data
|
||||
pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]);
|
||||
pObj->Num = 4 + i;
|
||||
assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 );
|
||||
pData = s_DarLib->pDatas + pObj->Num;
|
||||
pData->fMffc = 0;
|
||||
pData->pFunc = NULL;
|
||||
pData->TravId = 0xFFFF;
|
||||
|
||||
// explore the fanins
|
||||
assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 );
|
||||
assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 );
|
||||
pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num;
|
||||
pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num;
|
||||
pData->Level = 1 + AIG_MAX(pData0->Level, pData1->Level);
|
||||
if ( pData0->pFunc == NULL || pData1->pFunc == NULL )
|
||||
continue;
|
||||
pFanin0 = Aig_NotCond( pData0->pFunc, pObj->fCompl0 );
|
||||
pFanin1 = Aig_NotCond( pData1->pFunc, pObj->fCompl1 );
|
||||
pData->pFunc = Aig_TableLookupTwo( p->pAig, pFanin0, pFanin1 );
|
||||
if ( pData->pFunc )
|
||||
{
|
||||
// update the level to be more accurate
|
||||
pData->Level = Aig_Regular(pData->pFunc)->Level;
|
||||
// mark the node if it is part of MFFC
|
||||
pData->fMffc = Aig_ObjIsTravIdCurrent(p->pAig, pData->pFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluates one cut.]
|
||||
|
||||
Description [Returns the best gain.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required )
|
||||
{
|
||||
Dar_LibDat_t * pData;
|
||||
int Area;
|
||||
if ( pObj->fTerm )
|
||||
return 0;
|
||||
assert( pObj->Num > 3 );
|
||||
pData = s_DarLib->pDatas + pObj->Num;
|
||||
if ( pData->Level > Required )
|
||||
return 0xff;
|
||||
if ( pData->pFunc && !pData->fMffc )
|
||||
return 0;
|
||||
if ( pData->TravId == Out )
|
||||
return 0;
|
||||
pData->TravId = Out;
|
||||
// this is a new node - get a bound on the area of its branches
|
||||
nNodesSaved--;
|
||||
Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1 );
|
||||
if ( Area > nNodesSaved )
|
||||
return 0xff;
|
||||
Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1 );
|
||||
if ( Area > nNodesSaved )
|
||||
return 0xff;
|
||||
return Area + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluates one cut.]
|
||||
|
||||
Description [Returns the best gain.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required )
|
||||
{
|
||||
int fTraining = 0;
|
||||
Dar_LibObj_t * pObj;
|
||||
int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk;
|
||||
clk = clock();
|
||||
if ( pCut->nLeaves != 4 )
|
||||
return;
|
||||
// check if the cut exits and assigns leaves and their levels
|
||||
if ( !Dar_LibCutMatch(p, pCut) )
|
||||
return;
|
||||
// mark MFFC of the node
|
||||
nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves );
|
||||
// evaluate the cut
|
||||
Class = s_DarLib->pMap[pCut->uTruth];
|
||||
Dar_LibEvalAssignNums( p, Class );
|
||||
// profile outputs by their savings
|
||||
p->nTotalSubgs += s_DarLib->nSubgr0[Class];
|
||||
p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class];
|
||||
for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ )
|
||||
{
|
||||
pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]);
|
||||
if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot )
|
||||
continue;
|
||||
nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required );
|
||||
nNodesGained = nNodesSaved - nNodesAdded;
|
||||
if ( fTraining && nNodesGained >= 0 )
|
||||
Dar_LibIncrementScore( Class, Out, nNodesGained + 1 );
|
||||
if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) )
|
||||
continue;
|
||||
if ( nNodesGained < p->GainBest ||
|
||||
(nNodesGained == p->GainBest && s_DarLib->pDatas[pObj->Num].Level >= p->LevelBest) )
|
||||
continue;
|
||||
// remember this possibility
|
||||
Vec_PtrClear( p->vLeavesBest );
|
||||
for ( k = 0; k < (int)pCut->nLeaves; k++ )
|
||||
Vec_PtrPush( p->vLeavesBest, s_DarLib->pDatas[k].pFunc );
|
||||
p->OutBest = s_DarLib->pSubgr0[Class][Out];
|
||||
p->OutNumBest = Out;
|
||||
p->LevelBest = s_DarLib->pDatas[pObj->Num].Level;
|
||||
p->GainBest = nNodesGained;
|
||||
p->ClassBest = Class;
|
||||
assert( p->LevelBest <= Required );
|
||||
}
|
||||
clk = clock() - clk;
|
||||
p->ClassTimes[Class] += clk;
|
||||
p->timeEval += clk;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Clears the fields of the nodes used in this cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter )
|
||||
{
|
||||
if ( pObj->fTerm )
|
||||
return;
|
||||
pObj->Num = (*pCounter)++;
|
||||
s_DarLib->pDatas[ pObj->Num ].pFunc = NULL;
|
||||
Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter );
|
||||
Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reconstructs the best cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Dar_LibBuildBest_rec( Dar_Man_t * p, Dar_LibObj_t * pObj )
|
||||
{
|
||||
Aig_Obj_t * pFanin0, * pFanin1;
|
||||
Dar_LibDat_t * pData = s_DarLib->pDatas + pObj->Num;
|
||||
if ( pData->pFunc )
|
||||
return pData->pFunc;
|
||||
pFanin0 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) );
|
||||
pFanin1 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) );
|
||||
pFanin0 = Aig_NotCond( pFanin0, pObj->fCompl0 );
|
||||
pFanin1 = Aig_NotCond( pFanin1, pObj->fCompl1 );
|
||||
pData->pFunc = Aig_And( p->pAig, pFanin0, pFanin1 );
|
||||
// assert( pData->Level == (int)Aig_Regular(pData->pFunc)->Level );
|
||||
return pData->pFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reconstructs the best cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p )
|
||||
{
|
||||
int i, Counter = 4;
|
||||
for ( i = 0; i < Vec_PtrSize(p->vLeavesBest); i++ )
|
||||
s_DarLib->pDatas[i].pFunc = Vec_PtrEntry( p->vLeavesBest, i );
|
||||
Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, p->OutBest), &Counter );
|
||||
return Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, p->OutBest) );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [AIG manager.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the rewriting manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
|
||||
{
|
||||
Dar_Man_t * p;
|
||||
// start the manager
|
||||
p = ALLOC( Dar_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Dar_Man_t) );
|
||||
p->pPars = pPars;
|
||||
p->pAig = pAig;
|
||||
// prepare the internal memory manager
|
||||
p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 );
|
||||
// other data
|
||||
p->vLeavesBest = Vec_PtrAlloc( 4 );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the rewriting manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManStop( Dar_Man_t * p )
|
||||
{
|
||||
if ( p->pPars->fVerbose )
|
||||
Dar_ManPrintStats( p );
|
||||
if ( p->pMemCuts )
|
||||
Aig_MmFixedStop( p->pMemCuts, 0 );
|
||||
if ( p->vLeavesBest )
|
||||
Vec_PtrFree( p->vLeavesBest );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManPrintStats( Dar_Man_t * p )
|
||||
{
|
||||
unsigned pCanons[222];
|
||||
int Gain, i;
|
||||
extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
|
||||
|
||||
Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig);
|
||||
printf( "Tried = %8d. Beg = %8d. End = %8d. Gain = %6d. (%6.2f %%). Cut mem = %d Mb\n",
|
||||
p->nNodesTried, p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit, p->nCutMemUsed );
|
||||
printf( "Cuts = %8d. Tried = %8d. Used = %8d. Bad = %5d. Skipped = %5d. Ave = %.2f.\n",
|
||||
p->nCutsAll, p->nCutsTried, p->nCutsUsed, p->nCutsBad, p->nCutsSkipped,
|
||||
(float)p->nCutsUsed/Aig_ManNodeNum(p->pAig) );
|
||||
|
||||
printf( "Bufs = %5d. BufMax = %5d. BufReplace = %6d. BufFix = %6d. Levels = %4d.\n",
|
||||
Aig_ManBufNum(p->pAig), p->pAig->nBufMax, p->pAig->nBufReplaces, p->pAig->nBufFixes, Aig_ManLevels(p->pAig) );
|
||||
PRT( "Cuts ", p->timeCuts );
|
||||
PRT( "Eval ", p->timeEval );
|
||||
PRT( "Other ", p->timeOther );
|
||||
PRT( "TOTAL ", p->timeTotal );
|
||||
|
||||
if ( !p->pPars->fVeryVerbose )
|
||||
return;
|
||||
Dar_LibReturnCanonicals( pCanons );
|
||||
for ( i = 0; i < 222; i++ )
|
||||
{
|
||||
if ( p->ClassGains[i] == 0 && p->ClassTimes[i] == 0 )
|
||||
continue;
|
||||
printf( "%3d : ", i );
|
||||
printf( "G = %6d (%5.2f %%) ", p->ClassGains[i], Gain? 100.0*p->ClassGains[i]/Gain : 0.0 );
|
||||
printf( "S = %8d (%5.2f %%) ", p->ClassSubgs[i], p->nTotalSubgs? 100.0*p->ClassSubgs[i]/p->nTotalSubgs : 0.0 );
|
||||
printf( "R = %7d ", p->ClassGains[i]? p->ClassSubgs[i]/p->ClassGains[i] : 9999999 );
|
||||
Kit_DsdPrintFromTruth( pCanons + i, 4 );
|
||||
// PRTP( "T", p->ClassTimes[i], p->timeEval );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,591 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darRefact.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Refactoring.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
#include "kit.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// the refactoring manager
|
||||
typedef struct Ref_Man_t_ Ref_Man_t;
|
||||
struct Ref_Man_t_
|
||||
{
|
||||
// input data
|
||||
Dar_RefPar_t * pPars; // rewriting parameters
|
||||
Aig_Man_t * pAig; // AIG manager
|
||||
// computed cuts
|
||||
Vec_Vec_t * vCuts; // the storage for cuts
|
||||
// truth table and ISOP
|
||||
Vec_Ptr_t * vTruthElem; // elementary truth tables
|
||||
Vec_Ptr_t * vTruthStore; // storage for truth tables
|
||||
Vec_Int_t * vMemory; // storage for ISOP
|
||||
Vec_Ptr_t * vCutNodes; // storage for internal nodes of the cut
|
||||
// various data members
|
||||
Vec_Ptr_t * vLeavesBest; // the best set of leaves
|
||||
Kit_Graph_t * pGraphBest; // the best factored form
|
||||
int GainBest; // the best gain
|
||||
int LevelBest; // the level of node with the best gain
|
||||
// node statistics
|
||||
int nNodesInit; // the initial number of nodes
|
||||
int nNodesTried; // the number of nodes tried
|
||||
int nNodesBelow; // the number of nodes below the level limit
|
||||
int nNodesExten; // the number of nodes with extended cut
|
||||
int nCutsUsed; // the number of rewriting steps
|
||||
int nCutsTried; // the number of cuts tries
|
||||
// timing statistics
|
||||
int timeCuts;
|
||||
int timeEval;
|
||||
int timeOther;
|
||||
int timeTotal;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the structure with default assignment of parameters.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars )
|
||||
{
|
||||
memset( pPars, 0, sizeof(Dar_RefPar_t) );
|
||||
pPars->nMffcMin = 2; // the min MFFC size for which refactoring is used
|
||||
pPars->nLeafMax = 12; // the max number of leaves of a cut
|
||||
pPars->nCutsMax = 5; // the max number of cuts to consider
|
||||
pPars->fUpdateLevel = 0;
|
||||
pPars->fUseZeros = 0;
|
||||
pPars->fVerbose = 0;
|
||||
pPars->fVeryVerbose = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the rewriting manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars )
|
||||
{
|
||||
Ref_Man_t * p;
|
||||
// start the manager
|
||||
p = ALLOC( Ref_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Ref_Man_t) );
|
||||
p->pAig = pAig;
|
||||
p->pPars = pPars;
|
||||
// other data
|
||||
p->vCuts = Vec_VecStart( pPars->nCutsMax );
|
||||
p->vTruthElem = Vec_PtrAllocTruthTables( pPars->nLeafMax );
|
||||
p->vTruthStore = Vec_PtrAllocSimInfo( 256, Kit_TruthWordNum(pPars->nLeafMax) );
|
||||
p->vMemory = Vec_IntAlloc( 1 << 16 );
|
||||
p->vCutNodes = Vec_PtrAlloc( 256 );
|
||||
p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints out the statistics of the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManRefPrintStats( Ref_Man_t * p )
|
||||
{
|
||||
int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig);
|
||||
printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n",
|
||||
p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit );
|
||||
printf( "Tried = %6d. Below = %5d. Extended = %5d. Used = %5d. Levels = %4d.\n",
|
||||
p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) );
|
||||
PRT( "Cuts ", p->timeCuts );
|
||||
PRT( "Eval ", p->timeEval );
|
||||
PRT( "Other ", p->timeOther );
|
||||
PRT( "TOTAL ", p->timeTotal );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the rewriting manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Dar_ManRefStop( Ref_Man_t * p )
|
||||
{
|
||||
if ( p->pPars->fVerbose )
|
||||
Dar_ManRefPrintStats( p );
|
||||
Vec_VecFree( p->vCuts );
|
||||
Vec_PtrFree( p->vTruthElem );
|
||||
Vec_PtrFree( p->vTruthStore );
|
||||
Vec_PtrFree( p->vLeavesBest );
|
||||
Vec_IntFree( p->vMemory );
|
||||
Vec_PtrFree( p->vCutNodes );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts )
|
||||
{
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Ref_ObjPrint( Aig_Obj_t * pObj )
|
||||
{
|
||||
printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 );
|
||||
if ( pObj )
|
||||
printf( "(%d) ", Aig_IsComplement(pObj) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of new nodes added when using this graph.]
|
||||
|
||||
Description [AIG nodes for the fanins should be assigned to pNode->pFunc
|
||||
of the leaves of the graph before calling this procedure.
|
||||
Returns -1 if the number of nodes and levels exceeded the given limit or
|
||||
the number of levels exceeded the maximum allowed level.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax )
|
||||
{
|
||||
Kit_Node_t * pNode, * pNode0, * pNode1;
|
||||
Aig_Obj_t * pAnd, * pAnd0, * pAnd1;
|
||||
int i, Counter, LevelNew, LevelOld;
|
||||
// check for constant function or a literal
|
||||
if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) )
|
||||
return 0;
|
||||
// set the levels of the leaves
|
||||
Kit_GraphForEachLeaf( pGraph, pNode, i )
|
||||
{
|
||||
pNode->pFunc = Vec_PtrEntry(vCut, i);
|
||||
pNode->Level = Aig_Regular(pNode->pFunc)->Level;
|
||||
assert( Aig_Regular(pNode->pFunc)->Level < (1<<14)-1 );
|
||||
}
|
||||
//printf( "Trying:\n" );
|
||||
// compute the AIG size after adding the internal nodes
|
||||
Counter = 0;
|
||||
Kit_GraphForEachNode( pGraph, pNode, i )
|
||||
{
|
||||
// get the children of this node
|
||||
pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node );
|
||||
pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node );
|
||||
// get the AIG nodes corresponding to the children
|
||||
pAnd0 = pNode0->pFunc;
|
||||
pAnd1 = pNode1->pFunc;
|
||||
if ( pAnd0 && pAnd1 )
|
||||
{
|
||||
// if they are both present, find the resulting node
|
||||
pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl );
|
||||
pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl );
|
||||
pAnd = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 );
|
||||
// return -1 if the node is the same as the original root
|
||||
if ( Aig_Regular(pAnd) == pRoot )
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
pAnd = NULL;
|
||||
// count the number of added nodes
|
||||
if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) )
|
||||
{
|
||||
if ( ++Counter > NodeMax )
|
||||
return -1;
|
||||
}
|
||||
// count the number of new levels
|
||||
LevelNew = 1 + AIG_MAX( pNode0->Level, pNode1->Level );
|
||||
if ( pAnd )
|
||||
{
|
||||
if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) )
|
||||
LevelNew = 0;
|
||||
else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) )
|
||||
LevelNew = (int)Aig_Regular(pAnd0)->Level;
|
||||
else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) )
|
||||
LevelNew = (int)Aig_Regular(pAnd1)->Level;
|
||||
LevelOld = (int)Aig_Regular(pAnd)->Level;
|
||||
// assert( LevelNew == LevelOld );
|
||||
}
|
||||
if ( LevelNew > LevelMax )
|
||||
return -1;
|
||||
pNode->pFunc = pAnd;
|
||||
pNode->Level = LevelNew;
|
||||
/*
|
||||
printf( "Checking " );
|
||||
Ref_ObjPrint( pAnd0 );
|
||||
printf( " and " );
|
||||
Ref_ObjPrint( pAnd1 );
|
||||
printf( " Result " );
|
||||
Ref_ObjPrint( pNode->pFunc );
|
||||
printf( "\n" );
|
||||
*/
|
||||
}
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph )
|
||||
{
|
||||
Aig_Obj_t * pAnd0, * pAnd1;
|
||||
Kit_Node_t * pNode;
|
||||
int i;
|
||||
// check for constant function
|
||||
if ( Kit_GraphIsConst(pGraph) )
|
||||
return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) );
|
||||
// set the leaves
|
||||
Kit_GraphForEachLeaf( pGraph, pNode, i )
|
||||
pNode->pFunc = Vec_PtrEntry(vCut, i);
|
||||
// check for a literal
|
||||
if ( Kit_GraphIsVar(pGraph) )
|
||||
return Aig_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) );
|
||||
// build the AIG nodes corresponding to the AND gates of the graph
|
||||
//printf( "Building (current number %d):\n", Aig_ManObjIdMax(pAig) );
|
||||
Kit_GraphForEachNode( pGraph, pNode, i )
|
||||
{
|
||||
pAnd0 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
|
||||
pAnd1 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
|
||||
pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 );
|
||||
/*
|
||||
printf( "Checking " );
|
||||
Ref_ObjPrint( pAnd0 );
|
||||
printf( " and " );
|
||||
Ref_ObjPrint( pAnd1 );
|
||||
printf( " Result " );
|
||||
Ref_ObjPrint( pNode->pFunc );
|
||||
printf( "\n" );
|
||||
*/
|
||||
}
|
||||
// complement the result if necessary
|
||||
return Aig_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required )
|
||||
{
|
||||
Vec_Ptr_t * vCut;
|
||||
Kit_Graph_t * pGraphCur;
|
||||
int k, RetValue, GainCur, nNodesAdded;
|
||||
unsigned * pTruth;
|
||||
|
||||
p->GainBest = -1;
|
||||
p->pGraphBest = NULL;
|
||||
Vec_VecForEachLevel( p->vCuts, vCut, k )
|
||||
{
|
||||
if ( Vec_PtrSize(vCut) == 0 )
|
||||
continue;
|
||||
// if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 )
|
||||
// continue;
|
||||
|
||||
p->nCutsTried++;
|
||||
// get the cut nodes
|
||||
Aig_ObjCollectCut( pObj, vCut, p->vCutNodes );
|
||||
// get the truth table
|
||||
pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore );
|
||||
if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) )
|
||||
{
|
||||
p->GainBest = Vec_PtrSize(p->vCutNodes);
|
||||
p->pGraphBest = Kit_GraphCreateConst0();
|
||||
Vec_PtrCopy( p->vLeavesBest, vCut );
|
||||
return p->GainBest;
|
||||
}
|
||||
if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) )
|
||||
{
|
||||
p->GainBest = Vec_PtrSize(p->vCutNodes);
|
||||
p->pGraphBest = Kit_GraphCreateConst1();
|
||||
Vec_PtrCopy( p->vLeavesBest, vCut );
|
||||
return p->GainBest;
|
||||
}
|
||||
|
||||
// try the positive phase
|
||||
RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 );
|
||||
if ( RetValue > -1 )
|
||||
{
|
||||
pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory );
|
||||
nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required );
|
||||
if ( nNodesAdded > -1 )
|
||||
{
|
||||
GainCur = nNodesSaved - nNodesAdded;
|
||||
if ( p->GainBest < GainCur || (p->GainBest == GainCur &&
|
||||
(Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) )
|
||||
{
|
||||
p->GainBest = GainCur;
|
||||
if ( p->pGraphBest )
|
||||
Kit_GraphFree( p->pGraphBest );
|
||||
p->pGraphBest = pGraphCur;
|
||||
Vec_PtrCopy( p->vLeavesBest, vCut );
|
||||
}
|
||||
else
|
||||
Kit_GraphFree( pGraphCur );
|
||||
}
|
||||
else
|
||||
Kit_GraphFree( pGraphCur );
|
||||
}
|
||||
// try negative phase
|
||||
Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) );
|
||||
RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 );
|
||||
if ( RetValue > -1 )
|
||||
{
|
||||
pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory );
|
||||
nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required );
|
||||
if ( nNodesAdded > -1 )
|
||||
{
|
||||
GainCur = nNodesSaved - nNodesAdded;
|
||||
if ( p->GainBest < GainCur || (p->GainBest == GainCur &&
|
||||
(Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) )
|
||||
{
|
||||
p->GainBest = GainCur;
|
||||
if ( p->pGraphBest )
|
||||
Kit_GraphFree( p->pGraphBest );
|
||||
p->pGraphBest = pGraphCur;
|
||||
Vec_PtrCopy( p->vLeavesBest, vCut );
|
||||
}
|
||||
else
|
||||
Kit_GraphFree( pGraphCur );
|
||||
}
|
||||
else
|
||||
Kit_GraphFree( pGraphCur );
|
||||
}
|
||||
}
|
||||
return p->GainBest;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if a non-PI node has nLevelMin or below.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin )
|
||||
{
|
||||
Aig_Obj_t * pObj;
|
||||
int i;
|
||||
Vec_PtrForEachEntry( vCut, pObj, i )
|
||||
if ( !Aig_ObjIsPi(pObj) && (int)pObj->Level <= nLevelMin )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars )
|
||||
{
|
||||
ProgressBar * pProgress;
|
||||
Ref_Man_t * p;
|
||||
Vec_Ptr_t * vCut, * vCut2;
|
||||
Aig_Obj_t * pObj, * pObjNew;
|
||||
int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2;
|
||||
int i, Required, nLevelMin, clkStart, clk;
|
||||
|
||||
// start the manager
|
||||
p = Dar_ManRefStart( pAig, pPars );
|
||||
// remove dangling nodes
|
||||
Aig_ManCleanup( pAig );
|
||||
// if updating levels is requested, start fanout and timing
|
||||
Aig_ManFanoutStart( pAig );
|
||||
if ( p->pPars->fUpdateLevel )
|
||||
Aig_ManStartReverseLevels( pAig, 0 );
|
||||
|
||||
// resynthesize each node once
|
||||
clkStart = clock();
|
||||
vCut = Vec_VecEntry( p->vCuts, 0 );
|
||||
vCut2 = Vec_VecEntry( p->vCuts, 1 );
|
||||
p->nNodesInit = Aig_ManNodeNum(pAig);
|
||||
nNodesOld = Vec_PtrSize( pAig->vObjs );
|
||||
pProgress = Extra_ProgressBarStart( stdout, nNodesOld );
|
||||
Aig_ManForEachObj( pAig, pObj, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
if ( !Aig_ObjIsNode(pObj) )
|
||||
continue;
|
||||
if ( i > nNodesOld )
|
||||
break;
|
||||
Vec_VecClear( p->vCuts );
|
||||
|
||||
//printf( "\nConsidering node %d.\n", pObj->Id );
|
||||
// get the bounded MFFC size
|
||||
clk = clock();
|
||||
nLevelMin = AIG_MAX( 0, Aig_ObjLevel(pObj) - 10 );
|
||||
nNodesSaved = Aig_NodeMffsSupp( pAig, pObj, nLevelMin, vCut );
|
||||
if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider
|
||||
{
|
||||
p->timeCuts += clock() - clk;
|
||||
continue;
|
||||
}
|
||||
p->nNodesTried++;
|
||||
if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut
|
||||
{
|
||||
Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 );
|
||||
nNodesSaved = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut );
|
||||
}
|
||||
else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend )
|
||||
{
|
||||
if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) )
|
||||
{
|
||||
if ( Aig_NodeMffsExtendCut( pAig, pObj, vCut, vCut2 ) )
|
||||
{
|
||||
nNodesSaved2 = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut );
|
||||
assert( nNodesSaved2 == nNodesSaved );
|
||||
}
|
||||
if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax )
|
||||
Vec_PtrClear(vCut2);
|
||||
if ( Vec_PtrSize(vCut2) > 0 )
|
||||
{
|
||||
p->nNodesExten++;
|
||||
// printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) );
|
||||
}
|
||||
}
|
||||
else
|
||||
p->nNodesBelow++;
|
||||
}
|
||||
p->timeCuts += clock() - clk;
|
||||
|
||||
// try the cuts
|
||||
clk = clock();
|
||||
Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY;
|
||||
Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required );
|
||||
p->timeEval += clock() - clk;
|
||||
|
||||
// check the best gain
|
||||
if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) )
|
||||
{
|
||||
if ( p->pGraphBest )
|
||||
Kit_GraphFree( p->pGraphBest );
|
||||
continue;
|
||||
}
|
||||
//printf( "\n" );
|
||||
|
||||
// if we end up here, a rewriting step is accepted
|
||||
nNodeBefore = Aig_ManNodeNum( pAig );
|
||||
pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest );
|
||||
assert( (int)Aig_Regular(pObjNew)->Level <= Required );
|
||||
// replace the node
|
||||
Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel );
|
||||
// compare the gains
|
||||
nNodeAfter = Aig_ManNodeNum( pAig );
|
||||
assert( p->GainBest <= nNodeBefore - nNodeAfter );
|
||||
Kit_GraphFree( p->pGraphBest );
|
||||
p->nCutsUsed++;
|
||||
// break;
|
||||
}
|
||||
p->timeTotal = clock() - clkStart;
|
||||
p->timeOther = p->timeTotal - p->timeCuts - p->timeEval;
|
||||
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
// put the nodes into the DFS order and reassign their IDs
|
||||
// Aig_NtkReassignIds( p );
|
||||
// fix the levels
|
||||
Aig_ManFanoutStop( pAig );
|
||||
if ( p->pPars->fUpdateLevel )
|
||||
Aig_ManStopReverseLevels( pAig );
|
||||
|
||||
// stop the rewriting manager
|
||||
Dar_ManRefStop( p );
|
||||
Aig_ManCheckPhase( pAig );
|
||||
if ( !Aig_ManCheck( pAig ) )
|
||||
{
|
||||
printf( "Dar_ManRefactor: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darResub.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darResub.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darScript.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Rewriting scripts.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darScript.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs one iteration of AIG rewriting.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig )
|
||||
{
|
||||
Aig_Man_t * pTemp;
|
||||
Dar_RwrPar_t Pars, * pPars = &Pars;
|
||||
Dar_ManDefaultRwrParams( pPars );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
Dar_ManRewrite( pAig, pPars );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
return pAig;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reproduces script "compress2".]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects [This procedure does not tighten level during restructuring.]
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose )
|
||||
//alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
|
||||
{
|
||||
Aig_Man_t * pTemp;
|
||||
|
||||
Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
|
||||
Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
|
||||
|
||||
Dar_ManDefaultRwrParams( pParsRwr );
|
||||
Dar_ManDefaultRefParams( pParsRef );
|
||||
|
||||
pParsRwr->fUpdateLevel = fUpdateLevel;
|
||||
pParsRef->fUpdateLevel = fUpdateLevel;
|
||||
|
||||
pParsRwr->fVerbose = fVerbose;
|
||||
pParsRef->fVerbose = fVerbose;
|
||||
|
||||
// balance
|
||||
if ( fBalance )
|
||||
{
|
||||
// pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
|
||||
// Aig_ManStop( pTemp );
|
||||
}
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// refactor
|
||||
Dar_ManRefactor( pAig, pParsRef );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// balance
|
||||
// if ( fBalance )
|
||||
{
|
||||
pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
|
||||
Aig_ManStop( pTemp );
|
||||
}
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
pParsRwr->fUseZeros = 1;
|
||||
pParsRef->fUseZeros = 1;
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// balance
|
||||
if ( fBalance )
|
||||
{
|
||||
pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
|
||||
Aig_ManStop( pTemp );
|
||||
}
|
||||
|
||||
// refactor
|
||||
Dar_ManRefactor( pAig, pParsRef );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// balance
|
||||
if ( fBalance )
|
||||
{
|
||||
pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
|
||||
Aig_ManStop( pTemp );
|
||||
}
|
||||
return pAig;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reproduces script "compress2".]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects [This procedure does not tighten level during restructuring.]
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose )
|
||||
//alias rwsat "st; rw -l; b -l; rw -l; rf -l"
|
||||
{
|
||||
Aig_Man_t * pTemp;
|
||||
|
||||
Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
|
||||
Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
|
||||
|
||||
Dar_ManDefaultRwrParams( pParsRwr );
|
||||
Dar_ManDefaultRefParams( pParsRef );
|
||||
|
||||
pParsRwr->fUpdateLevel = 0;
|
||||
pParsRef->fUpdateLevel = 0;
|
||||
|
||||
pParsRwr->fVerbose = fVerbose;
|
||||
pParsRef->fVerbose = fVerbose;
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// refactor
|
||||
Dar_ManRefactor( pAig, pParsRef );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
// balance
|
||||
if ( fBalance )
|
||||
{
|
||||
pAig = Dar_ManBalance( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
}
|
||||
|
||||
// rewrite
|
||||
Dar_ManRewrite( pAig, pParsRwr );
|
||||
pAig = Aig_ManDup( pTemp = pAig, 0 );
|
||||
Aig_ManStop( pTemp );
|
||||
|
||||
return pAig;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [darTruth.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis [Computes the truth table of a cut.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: darTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCollectCut_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vNodes )
|
||||
{
|
||||
if ( pNode->fMarkA )
|
||||
return;
|
||||
pNode->fMarkA = 1;
|
||||
assert( Aig_ObjIsAnd(pNode) || Aig_ObjIsExor(pNode) );
|
||||
Aig_ManCollectCut_rec( p, Aig_ObjFanin0(pNode), vNodes );
|
||||
Aig_ManCollectCut_rec( p, Aig_ObjFanin1(pNode), vNodes );
|
||||
Vec_IntPush( vNodes, pNode->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description [Does not modify the array of leaves. Uses array vTruth to store
|
||||
temporary truth tables. The returned pointer should be used immediately.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCollectCut( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
|
||||
{
|
||||
int i, Leaf;
|
||||
// collect and mark the leaves
|
||||
Vec_IntClear( vNodes );
|
||||
Vec_IntForEachEntry( vLeaves, Leaf, i )
|
||||
{
|
||||
Vec_IntPush( vNodes, Leaf );
|
||||
Aig_ManObj(p, Leaf)->fMarkA = 1;
|
||||
}
|
||||
// collect and mark the nodes
|
||||
Aig_ManCollectCut_rec( p, pRoot, vNodes );
|
||||
// clean the nodes
|
||||
Vec_IntForEachEntry( vNodes, Leaf, i )
|
||||
Aig_ManObj(p, Leaf)->fMarkA = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the pointer to the truth table.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned * Aig_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth )
|
||||
{
|
||||
return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManCutTruthOne( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vTruth, int nWords )
|
||||
{
|
||||
unsigned * pTruth, * pTruth0, * pTruth1;
|
||||
int i;
|
||||
pTruth = Aig_ObjGetTruthStore( pNode->Level, vTruth );
|
||||
pTruth0 = Aig_ObjGetTruthStore( Aig_ObjFanin0(pNode)->Level, vTruth );
|
||||
pTruth1 = Aig_ObjGetTruthStore( Aig_ObjFanin1(pNode)->Level, vTruth );
|
||||
if ( Aig_ObjIsExor(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] ^ pTruth1[i];
|
||||
else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] & pTruth1[i];
|
||||
else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = pTruth0[i] & ~pTruth1[i];
|
||||
else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = ~pTruth0[i] & pTruth1[i];
|
||||
else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description [Does not modify the array of leaves. Uses array vTruth to store
|
||||
temporary truth tables. The returned pointer should be used immediately.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
unsigned * Aig_ManCutTruth( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth )
|
||||
{
|
||||
static unsigned uTruths[8][8] = { // elementary truth tables
|
||||
{ 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
|
||||
{ 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
|
||||
{ 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
|
||||
{ 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
|
||||
{ 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
|
||||
{ 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
|
||||
{ 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
|
||||
{ 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
|
||||
};
|
||||
int i, Leaf;
|
||||
// collect the cut
|
||||
// Aig_ManCollectCut( p, pRoot, vLeaves, vNodes );
|
||||
// set the node numbers
|
||||
Vec_IntForEachEntry( vNodes, Leaf, i )
|
||||
Aig_ManObj(p, Leaf)->Level = i;
|
||||
// alloc enough memory
|
||||
Vec_IntClear( vTruth );
|
||||
Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) );
|
||||
// set the elementary truth tables
|
||||
Vec_IntForEachEntry( vLeaves, Leaf, i )
|
||||
memcpy( Aig_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) );
|
||||
// compute truths for other nodes
|
||||
Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) )
|
||||
Aig_ManCutTruthOne( p, Aig_ManObj(p, Leaf), vTruth, 8 );
|
||||
return Aig_ObjGetTruthStore( pRoot->Level, vTruth );
|
||||
}
|
||||
|
||||
static inline int Kit_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
|
||||
static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
|
||||
{
|
||||
int w;
|
||||
for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
|
||||
pOut[w] = ~pIn[w];
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the cost based on two ISOPs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManLargeCutEvalIsop( unsigned * pTruth, int nVars, Vec_Int_t * vMemory )
|
||||
{
|
||||
extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth );
|
||||
int RetValue, nClauses;
|
||||
// compute ISOP for the positive phase
|
||||
RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 0 );
|
||||
if ( RetValue == -1 )
|
||||
return AIG_INFINITY;
|
||||
assert( RetValue == 0 || RetValue == 1 );
|
||||
nClauses = Vec_IntSize( vMemory );
|
||||
// compute ISOP for the negative phase
|
||||
Kit_TruthNot( pTruth, pTruth, nVars );
|
||||
RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 0 );
|
||||
if ( RetValue == -1 )
|
||||
return AIG_INFINITY;
|
||||
Kit_TruthNot( pTruth, pTruth, nVars );
|
||||
assert( RetValue == 0 || RetValue == 1 );
|
||||
nClauses += Vec_IntSize( vMemory );
|
||||
return nClauses;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes truth table of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManLargeCutCollect_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
|
||||
{
|
||||
if ( Aig_ObjIsTravIdCurrent(p, pNode) )
|
||||
return;
|
||||
if ( Aig_ObjIsTravIdPrevious(p, pNode) )
|
||||
{
|
||||
Vec_IntPush( vLeaves, pNode->Id );
|
||||
// Vec_IntPush( vNodes, pNode->Id );
|
||||
Aig_ObjSetTravIdCurrent( p, pNode );
|
||||
return;
|
||||
}
|
||||
assert( Aig_ObjIsAnd(pNode) || Aig_ObjIsExor(pNode) );
|
||||
Aig_ObjSetTravIdCurrent( p, pNode );
|
||||
Aig_ManLargeCutCollect_rec( p, Aig_ObjFanin0(pNode), vLeaves, vNodes );
|
||||
Aig_ManLargeCutCollect_rec( p, Aig_ObjFanin1(pNode), vLeaves, vNodes );
|
||||
Vec_IntPush( vNodes, pNode->Id );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collect leaves and nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Aig_ManLargeCutCollect( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Cut_t * pCutR, Aig_Cut_t * pCutL, int Leaf,
|
||||
Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
|
||||
{
|
||||
Vec_Int_t * vTemp;
|
||||
Aig_Obj_t * pObj;
|
||||
int Node, i;
|
||||
|
||||
Aig_ManIncrementTravId( p );
|
||||
Aig_CutForEachLeaf( p, pCutR, pObj, i )
|
||||
if ( pObj->Id != Leaf )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
Aig_CutForEachLeaf( p, pCutL, pObj, i )
|
||||
Aig_ObjSetTravIdCurrent( p, pObj );
|
||||
|
||||
// collect the internal nodes and leaves
|
||||
Aig_ManIncrementTravId( p );
|
||||
vTemp = Vec_IntAlloc( 100 );
|
||||
Aig_ManLargeCutCollect_rec( p, pRoot, vLeaves, vTemp );
|
||||
|
||||
Vec_IntForEachEntry( vLeaves, Node, i )
|
||||
Vec_IntPush( vNodes, Node );
|
||||
Vec_IntForEachEntry( vTemp, Node, i )
|
||||
Vec_IntPush( vNodes, Node );
|
||||
|
||||
Vec_IntFree( vTemp );
|
||||
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Cut_t * pCutR, Aig_Cut_t * pCutL, int Leaf )
|
||||
{
|
||||
Vec_Int_t * vLeaves, * vNodes, * vTruth, * vMemory;
|
||||
unsigned * pTruth;
|
||||
int RetValue;
|
||||
// Aig_Obj_t * pObj;
|
||||
|
||||
vMemory = Vec_IntAlloc( 1 << 16 );
|
||||
vTruth = Vec_IntAlloc( 1 << 16 );
|
||||
vLeaves = Vec_IntAlloc( 100 );
|
||||
vNodes = Vec_IntAlloc( 100 );
|
||||
|
||||
Aig_ManLargeCutCollect( p, pRoot, pCutR, pCutL, Leaf, vLeaves, vNodes );
|
||||
/*
|
||||
// collect the nodes
|
||||
Aig_CutForEachLeaf( p, pCutR, pObj, i )
|
||||
{
|
||||
if ( pObj->Id == Leaf )
|
||||
continue;
|
||||
if ( pObj->fMarkA )
|
||||
continue;
|
||||
pObj->fMarkA = 1;
|
||||
Vec_IntPush( vLeaves, pObj->Id );
|
||||
Vec_IntPush( vNodes, pObj->Id );
|
||||
}
|
||||
Aig_CutForEachLeaf( p, pCutL, pObj, i )
|
||||
{
|
||||
if ( pObj->fMarkA )
|
||||
continue;
|
||||
pObj->fMarkA = 1;
|
||||
Vec_IntPush( vLeaves, pObj->Id );
|
||||
Vec_IntPush( vNodes, pObj->Id );
|
||||
}
|
||||
// collect and mark the nodes
|
||||
Aig_ManCollectCut_rec( p, pRoot, vNodes );
|
||||
// clean the nodes
|
||||
Vec_IntForEachEntry( vNodes, Leaf, i )
|
||||
Aig_ManObj(p, Leaf)->fMarkA = 0;
|
||||
*/
|
||||
|
||||
pTruth = Aig_ManCutTruth( p, pRoot, vLeaves, vNodes, vTruth );
|
||||
RetValue = Aig_ManLargeCutEvalIsop( pTruth, Vec_IntSize(vLeaves), vMemory );
|
||||
|
||||
Vec_IntFree( vLeaves );
|
||||
Vec_IntFree( vNodes );
|
||||
Vec_IntFree( vTruth );
|
||||
Vec_IntFree( vMemory );
|
||||
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [dar_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [DAG-aware AIG rewriting.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - April 28, 2007.]
|
||||
|
||||
Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "darInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
SRC += src/aig/dar/darBalance.c \
|
||||
src/aig/dar/darCore.c \
|
||||
src/aig/dar/darCut.c \
|
||||
src/aig/dar/darData.c \
|
||||
src/aig/dar/darLib.c \
|
||||
src/aig/dar/darMan.c \
|
||||
src/aig/dar/darRefact.c \
|
||||
src/aig/dar/darResub.c \
|
||||
src/aig/dar/darScript.c \
|
||||
src/aig/dar/darTruth.c
|
|
@ -0,0 +1,703 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [deco.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [A simple decomposition tree/node data structure and its APIs.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __DEC_H__
|
||||
#define __DEC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Dec_Edge_t_ Dec_Edge_t;
|
||||
struct Dec_Edge_t_
|
||||
{
|
||||
unsigned fCompl : 1; // the complemented bit
|
||||
unsigned Node : 30; // the decomposition node pointed by the edge
|
||||
};
|
||||
|
||||
typedef struct Dec_Node_t_ Dec_Node_t;
|
||||
struct Dec_Node_t_
|
||||
{
|
||||
Dec_Edge_t eEdge0; // the left child of the node
|
||||
Dec_Edge_t eEdge1; // the right child of the node
|
||||
// other info
|
||||
void * pFunc; // the function of the node (BDD or AIG)
|
||||
unsigned Level : 14; // the level of this node in the global AIG
|
||||
// printing info
|
||||
unsigned fNodeOr : 1; // marks the original OR node
|
||||
unsigned fCompl0 : 1; // marks the original complemented edge
|
||||
unsigned fCompl1 : 1; // marks the original complemented edge
|
||||
// latch info
|
||||
unsigned nLat0 : 5; // the number of latches on the first edge
|
||||
unsigned nLat1 : 5; // the number of latches on the second edge
|
||||
unsigned nLat2 : 5; // the number of latches on the output edge
|
||||
};
|
||||
|
||||
typedef struct Dec_Graph_t_ Dec_Graph_t;
|
||||
struct Dec_Graph_t_
|
||||
{
|
||||
int fConst; // marks the constant 1 graph
|
||||
int nLeaves; // the number of leaves
|
||||
int nSize; // the number of nodes (including the leaves)
|
||||
int nCap; // the number of allocated nodes
|
||||
Dec_Node_t * pNodes; // the array of leaves and internal nodes
|
||||
Dec_Edge_t eRoot; // the pointer to the topmost node
|
||||
};
|
||||
|
||||
typedef struct Dec_Man_t_ Dec_Man_t;
|
||||
struct Dec_Man_t_
|
||||
{
|
||||
void * pMvcMem; // memory manager for MVC cover (used for factoring)
|
||||
Vec_Int_t * vCubes; // storage for cubes
|
||||
Vec_Int_t * vLits; // storage for literals
|
||||
// precomputation information about 4-variable functions
|
||||
unsigned short * puCanons; // canonical forms
|
||||
char * pPhases; // canonical phases
|
||||
char * pPerms; // canonical permutations
|
||||
unsigned char * pMap; // mapping of functions into class numbers
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// interator throught the leaves
|
||||
#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \
|
||||
for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ )
|
||||
// interator throught the internal nodes
|
||||
#define Dec_GraphForEachNode( pGraph, pAnd, i ) \
|
||||
for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates an edge pointing to the node in the given polarity.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl )
|
||||
{
|
||||
Dec_Edge_t eEdge = { fCompl, Node };
|
||||
return eEdge;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts the edge into unsigned integer.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge )
|
||||
{
|
||||
return (eEdge.Node << 1) | eEdge.fCompl;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts unsigned integer into the edge.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge )
|
||||
{
|
||||
return Dec_EdgeCreate( Edge >> 1, Edge & 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts the edge into unsigned integer.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge )
|
||||
{
|
||||
return *(unsigned *)&eEdge;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Converts unsigned integer into the edge.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge )
|
||||
{
|
||||
return *(Dec_Edge_t *)&Edge;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates a graph with the given number of leaves.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves )
|
||||
{
|
||||
Dec_Graph_t * pGraph;
|
||||
pGraph = ALLOC( Dec_Graph_t, 1 );
|
||||
memset( pGraph, 0, sizeof(Dec_Graph_t) );
|
||||
pGraph->nLeaves = nLeaves;
|
||||
pGraph->nSize = nLeaves;
|
||||
pGraph->nCap = 2 * nLeaves + 50;
|
||||
pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap );
|
||||
memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize );
|
||||
return pGraph;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates constant 0 graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Graph_t * Dec_GraphCreateConst0()
|
||||
{
|
||||
Dec_Graph_t * pGraph;
|
||||
pGraph = ALLOC( Dec_Graph_t, 1 );
|
||||
memset( pGraph, 0, sizeof(Dec_Graph_t) );
|
||||
pGraph->fConst = 1;
|
||||
pGraph->eRoot.fCompl = 1;
|
||||
return pGraph;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates constant 1 graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Graph_t * Dec_GraphCreateConst1()
|
||||
{
|
||||
Dec_Graph_t * pGraph;
|
||||
pGraph = ALLOC( Dec_Graph_t, 1 );
|
||||
memset( pGraph, 0, sizeof(Dec_Graph_t) );
|
||||
pGraph->fConst = 1;
|
||||
return pGraph;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates the literal graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )
|
||||
{
|
||||
Dec_Graph_t * pGraph;
|
||||
assert( 0 <= iLeaf && iLeaf < nLeaves );
|
||||
pGraph = Dec_GraphCreate( nLeaves );
|
||||
pGraph->eRoot.Node = iLeaf;
|
||||
pGraph->eRoot.fCompl = fCompl;
|
||||
return pGraph;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates a graph with the given number of leaves.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Dec_GraphFree( Dec_Graph_t * pGraph )
|
||||
{
|
||||
FREE( pGraph->pNodes );
|
||||
free( pGraph );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the graph is a constant.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->fConst;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the graph is constant 0.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->fConst && pGraph->eRoot.fCompl;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the graph is constant 1.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->fConst && !pGraph->eRoot.fCompl;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the graph is complemented.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->eRoot.fCompl;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if the graph is complemented.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Dec_GraphComplement( Dec_Graph_t * pGraph )
|
||||
{
|
||||
pGraph->eRoot.fCompl ^= 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of leaves.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->nLeaves;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of internal nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->nSize - pGraph->nLeaves;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the pointer to the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i )
|
||||
{
|
||||
return pGraph->pNodes + i;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the pointer to the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->pNodes + pGraph->nSize - 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of the given node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
|
||||
{
|
||||
return pNode - pGraph->pNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Check if the graph represents elementary variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )
|
||||
{
|
||||
return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Check if the graph represents elementary variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
|
||||
{
|
||||
return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the elementary variable elementary variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph )
|
||||
{
|
||||
assert( Dec_GraphIsVar( pGraph ) );
|
||||
return Dec_GraphNode( pGraph, pGraph->eRoot.Node );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the number of the elementary variable.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph )
|
||||
{
|
||||
assert( Dec_GraphIsVar( pGraph ) );
|
||||
return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the root of the graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot )
|
||||
{
|
||||
pGraph->eRoot = eRoot;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Appends a new node to the graph.]
|
||||
|
||||
Description [This procedure is meant for internal use.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph )
|
||||
{
|
||||
Dec_Node_t * pNode;
|
||||
if ( pGraph->nSize == pGraph->nCap )
|
||||
{
|
||||
pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap );
|
||||
pGraph->nCap = 2 * pGraph->nCap;
|
||||
}
|
||||
pNode = pGraph->pNodes + pGraph->nSize++;
|
||||
memset( pNode, 0, sizeof(Dec_Node_t) );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates an AND node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
|
||||
{
|
||||
Dec_Node_t * pNode;
|
||||
// get the new node
|
||||
pNode = Dec_GraphAppendNode( pGraph );
|
||||
// set the inputs and other info
|
||||
pNode->eEdge0 = eEdge0;
|
||||
pNode->eEdge1 = eEdge1;
|
||||
pNode->fCompl0 = eEdge0.fCompl;
|
||||
pNode->fCompl1 = eEdge1.fCompl;
|
||||
return Dec_EdgeCreate( pGraph->nSize - 1, 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates an OR node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
|
||||
{
|
||||
Dec_Node_t * pNode;
|
||||
// get the new node
|
||||
pNode = Dec_GraphAppendNode( pGraph );
|
||||
// set the inputs and other info
|
||||
pNode->eEdge0 = eEdge0;
|
||||
pNode->eEdge1 = eEdge1;
|
||||
pNode->fCompl0 = eEdge0.fCompl;
|
||||
pNode->fCompl1 = eEdge1.fCompl;
|
||||
// make adjustments for the OR gate
|
||||
pNode->fNodeOr = 1;
|
||||
pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
|
||||
pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
|
||||
return Dec_EdgeCreate( pGraph->nSize - 1, 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates an XOR node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
|
||||
{
|
||||
Dec_Edge_t eNode0, eNode1, eNode;
|
||||
if ( Type == 0 )
|
||||
{
|
||||
// derive the first AND
|
||||
eEdge0.fCompl ^= 1;
|
||||
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
|
||||
eEdge0.fCompl ^= 1;
|
||||
// derive the second AND
|
||||
eEdge1.fCompl ^= 1;
|
||||
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
|
||||
// derive the final OR
|
||||
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// derive the first AND
|
||||
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
|
||||
// derive the second AND
|
||||
eEdge0.fCompl ^= 1;
|
||||
eEdge1.fCompl ^= 1;
|
||||
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
|
||||
// derive the final OR
|
||||
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
|
||||
eNode.fCompl ^= 1;
|
||||
}
|
||||
return eNode;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates an XOR node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
|
||||
{
|
||||
Dec_Edge_t eNode0, eNode1, eNode;
|
||||
if ( Type == 0 )
|
||||
{
|
||||
// derive the first AND
|
||||
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
|
||||
// derive the second AND
|
||||
eEdgeC.fCompl ^= 1;
|
||||
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
|
||||
// derive the final OR
|
||||
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// complement the arguments
|
||||
eEdgeT.fCompl ^= 1;
|
||||
eEdgeE.fCompl ^= 1;
|
||||
// derive the first AND
|
||||
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
|
||||
// derive the second AND
|
||||
eEdgeC.fCompl ^= 1;
|
||||
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
|
||||
// derive the final OR
|
||||
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
|
||||
eNode.fCompl ^= 1;
|
||||
}
|
||||
return eNode;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1 @@
|
|||
SRC +=
|
|
@ -0,0 +1 @@
|
|||
SRC +=
|
|
@ -0,0 +1,238 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [fra.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [[New FRAIG package.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 30, 2007.]
|
||||
|
||||
Revision [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __FRA_H__
|
||||
#define __FRA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "vec.h"
|
||||
#include "aig.h"
|
||||
#include "dar.h"
|
||||
#include "satSolver.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Fra_Par_t_ Fra_Par_t;
|
||||
typedef struct Fra_Cla_t_ Fra_Cla_t;
|
||||
typedef struct Fra_Man_t_ Fra_Man_t;
|
||||
|
||||
// FRAIG parameters
|
||||
struct Fra_Par_t_
|
||||
{
|
||||
int nSimWords; // the number of words in the simulation info
|
||||
double dSimSatur; // the ratio of refined classes when saturation is reached
|
||||
int fPatScores; // enables simulation pattern scoring
|
||||
int MaxScore; // max score after which resimulation is used
|
||||
double dActConeRatio; // the ratio of cone to be bumped
|
||||
double dActConeBumpMax; // the largest bump in activity
|
||||
int fChoicing; // enables choicing
|
||||
int fSpeculate; // use speculative reduction
|
||||
int fProve; // prove the miter outputs
|
||||
int fVerbose; // verbose output
|
||||
int fDoSparse; // skip sparse functions
|
||||
int fConeBias; // bias variables in the cone (good for unsat runs)
|
||||
int nBTLimitNode; // conflict limit at a node
|
||||
int nBTLimitMiter; // conflict limit at an output
|
||||
int nFramesK; // the number of timeframes to unroll
|
||||
int fRewrite; // use rewriting for constraint reduction
|
||||
};
|
||||
|
||||
// FRAIG equivalence classes
|
||||
struct Fra_Cla_t_
|
||||
{
|
||||
Aig_Man_t * pAig; // the original AIG manager
|
||||
Aig_Obj_t ** pMemRepr; // pointers to representatives of each node
|
||||
Vec_Ptr_t * vClasses; // equivalence classes
|
||||
Vec_Ptr_t * vClasses1; // equivalence class of Const1 node
|
||||
Vec_Ptr_t * vClassesTemp; // temporary storage for new classes
|
||||
Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes
|
||||
Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used
|
||||
Vec_Ptr_t * vClassOld; // old equivalence class after splitting
|
||||
Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting
|
||||
int nPairs; // the number of pairs of nodes
|
||||
int fRefinement; // set to 1 when refinement has happened
|
||||
};
|
||||
|
||||
// FRAIG manager
|
||||
struct Fra_Man_t_
|
||||
{
|
||||
// high-level data
|
||||
Fra_Par_t * pPars; // parameters governing fraiging
|
||||
// AIG managers
|
||||
Aig_Man_t * pManAig; // the starting AIG manager
|
||||
Aig_Man_t * pManFraig; // the final AIG manager
|
||||
// mapping AIG into FRAIG
|
||||
int nFramesAll; // the number of timeframes used
|
||||
Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes
|
||||
// simulation info
|
||||
unsigned * pSimWords; // memory for simulation information
|
||||
int nSimWords; // the number of simulation words
|
||||
// counter example storage
|
||||
int nPatWords; // the number of words in the counter example
|
||||
unsigned * pPatWords; // the counter example
|
||||
int * pPatScores; // the scores of each pattern
|
||||
// equivalence classes
|
||||
Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes
|
||||
// equivalence checking
|
||||
sat_solver * pSat; // SAT solver
|
||||
int nSatVars; // the number of variables currently used
|
||||
Vec_Ptr_t * vPiVars; // the PIs of the cone used
|
||||
sint64 nBTLimitGlobal; // resource limit
|
||||
sint64 nInsLimitGlobal; // resource limit
|
||||
Vec_Ptr_t ** pMemFanins; // the arrays of fanins for some FRAIG nodes
|
||||
int * pMemSatNums; // the array of SAT numbers for some FRAIG nodes
|
||||
int nSizeAlloc; // allocated size of the arrays
|
||||
Vec_Ptr_t * vTimeouts; // the nodes, for which equivalence checking timed out
|
||||
// statistics
|
||||
int nSimRounds;
|
||||
int nNodesMiter;
|
||||
int nLitsZero;
|
||||
int nLitsBeg;
|
||||
int nLitsEnd;
|
||||
int nNodesBeg;
|
||||
int nNodesEnd;
|
||||
int nRegsBeg;
|
||||
int nRegsEnd;
|
||||
int nSatCalls;
|
||||
int nSatCallsSat;
|
||||
int nSatCallsUnsat;
|
||||
int nSatProof;
|
||||
int nSatFails;
|
||||
int nSatFailsReal;
|
||||
int nSpeculs;
|
||||
int nChoices;
|
||||
int nChoicesFake;
|
||||
// runtime
|
||||
int timeSim;
|
||||
int timeTrav;
|
||||
int timeRwr;
|
||||
int timeSat;
|
||||
int timeSatUnsat;
|
||||
int timeSatSat;
|
||||
int timeSatFail;
|
||||
int timeRef;
|
||||
int timeTotal;
|
||||
int time1;
|
||||
int time2;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline unsigned * Fra_ObjSim( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pSimWords + ((Fra_Man_t *)pObj->pData)->nSimWords * pObj->Id; }
|
||||
static inline unsigned Fra_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); }
|
||||
|
||||
static inline Aig_Obj_t * Fra_ObjFraig( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i]; }
|
||||
static inline void Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; }
|
||||
|
||||
static inline Vec_Ptr_t * Fra_ObjFaninVec( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id]; }
|
||||
static inline void Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins ) { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins; }
|
||||
|
||||
static inline int Fra_ObjSatNum( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id]; }
|
||||
static inline void Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num ) { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num; }
|
||||
|
||||
static inline Aig_Obj_t * Fra_ClassObjRepr( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id]; }
|
||||
static inline void Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; }
|
||||
|
||||
static inline Aig_Obj_t * Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; }
|
||||
static inline Aig_Obj_t * Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== fraClass.c ========================================================*/
|
||||
extern Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig );
|
||||
extern void Fra_ClassesStop( Fra_Cla_t * p );
|
||||
extern void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed );
|
||||
extern void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose );
|
||||
extern void Fra_ClassesPrepare( Fra_Cla_t * p );
|
||||
extern int Fra_ClassesRefine( Fra_Cla_t * p );
|
||||
extern int Fra_ClassesRefine1( Fra_Cla_t * p );
|
||||
extern int Fra_ClassesCountLits( Fra_Cla_t * p );
|
||||
extern int Fra_ClassesCountPairs( Fra_Cla_t * p );
|
||||
extern void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 );
|
||||
/*=== fraCnf.c ========================================================*/
|
||||
extern void Fra_NodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
|
||||
/*=== fraCore.c ========================================================*/
|
||||
extern Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars );
|
||||
extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig );
|
||||
extern void Fra_FraigSweep( Fra_Man_t * pManAig );
|
||||
extern int Fra_FraigMiterStatus( Aig_Man_t * p );
|
||||
/*=== fraDfs.c ========================================================*/
|
||||
/*=== fraInd.c ========================================================*/
|
||||
extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * p, int nFramesK, int fRewrite, int fVerbose, int * pnIter );
|
||||
/*=== fraMan.c ========================================================*/
|
||||
extern void Fra_ParamsDefault( Fra_Par_t * pParams );
|
||||
extern void Fra_ParamsDefaultSeq( Fra_Par_t * pParams );
|
||||
extern Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams );
|
||||
extern void Fra_ManClean( Fra_Man_t * p );
|
||||
extern Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p );
|
||||
extern void Fra_ManFinalizeComb( Fra_Man_t * p );
|
||||
extern void Fra_ManStop( Fra_Man_t * p );
|
||||
extern void Fra_ManPrint( Fra_Man_t * p );
|
||||
/*=== fraSat.c ========================================================*/
|
||||
extern int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
|
||||
extern int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew );
|
||||
/*=== fraSec.c ========================================================*/
|
||||
extern int Fra_FraigSec( Aig_Man_t * p, int nFrames, int fVerbose, int fVeryVerbose );
|
||||
/*=== fraSim.c ========================================================*/
|
||||
extern int Fra_NodeHasZeroSim( Aig_Obj_t * pObj );
|
||||
extern int Fra_NodeCompareSims( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
|
||||
extern unsigned Fra_NodeHashSims( Aig_Obj_t * pObj );
|
||||
extern void Fra_SavePattern( Fra_Man_t * p );
|
||||
extern void Fra_Simulate( Fra_Man_t * p, int fInit );
|
||||
extern void Fra_Resimulate( Fra_Man_t * p );
|
||||
extern int Fra_CheckOutputSims( Fra_Man_t * p );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [fraCec.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New FRAIG package.]
|
||||
|
||||
Synopsis [CEC engined based on fraiging.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 30, 2007.]
|
||||
|
||||
Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "fra.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue