Add ABC and ACE2, fix bugs for fpga_flow and VPR

This commit is contained in:
Xifan Tang 2018-07-27 22:54:52 -06:00
parent b9d583519b
commit fe13168f8f
797 changed files with 374608 additions and 6 deletions

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

2819
abc_with_bb_support/abc.dsp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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>
{{{
}}}
###############################################################################

BIN
abc_with_bb_support/abc.ncb Normal file

Binary file not shown.

174
abc_with_bb_support/abc.rc Normal file
View File

@ -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"

BIN
abc_with_bb_support/abc.suo Normal file

Binary file not shown.

12366
abc_with_bb_support/abc.vcproj Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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>
{{{
}}}
###############################################################################

View File

@ -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

View File

@ -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>
{{{
}}}
###############################################################################

View File

@ -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

View File

@ -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

View File

@ -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.

181
abc_with_bb_support/demo.c Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,4 @@
SRC += src/aig/bdc/bdcCore.c \
src/aig/bdc/bdcDec.c \
src/aig/bdc/bdcTable.c

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///
////////////////////////////////////////////////////////////////////////

View 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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1 @@
SRC +=

View File

@ -0,0 +1 @@
SRC +=

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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