summaryrefslogtreecommitdiffstats
path: root/src/demo.c
blob: eebb8aba0f655b42f95724559214237d3af5e027 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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];
    clock_t 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;
}
ass="n">var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; return FALSE; /* disjoint in this variable */ nextvar: ; } } return TRUE; } /* cdist01 -- return the "distance" between two cubes (defined as the number of null variables in their intersection). If the distance exceeds 1, the value 2 is returned. */ int cdist01(a, b) register pset a, b; { int dist = 0; { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~ (x | x >> 1) & cube.inmask)) if ((dist = count_ones(x)) > 1) return 2; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~ (x | x >> 1) & DISJOINT)) if (dist == 1 || (dist += count_ones(x)) > 1) return 2; } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; if (++dist > 1) return 2; nextvar: ; } } return dist; } /* cdist -- return the "distance" between two cubes (defined as the number of null variables in their intersection). */ int cdist(a, b) register pset a, b; { int dist = 0; { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~ (x | x >> 1) & cube.inmask)) dist = count_ones(x); /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~ (x | x >> 1) & DISJOINT)) dist += count_ones(x); } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; dist++; nextvar: ; } } return dist; } /* force_lower -- Determine which variables of a do not intersect b. */ pset force_lower(xlower, a, b) INOUT pset xlower; IN register pset a, b; { { /* Check binary variables (if any) */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~(x | x >> 1) & cube.inmask)) xlower[last] |= (x | (x << 1)) & a[last]; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~(x | x >> 1) & DISJOINT)) xlower[w] |= (x | (x << 1)) & a[w]; } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; for(w = cube.first_word[var]; w <= last; w++) xlower[w] |= a[w] & mask[w]; nextvar: ; } } return xlower; } /* consensus -- multiple-valued consensus Although this looks very messy, the idea is to compute for r the "and" of the cubes a and b for each variable, unless the "and" is null in a variable, in which case the "or" of a and b is computed for this variable. Because we don't check how many variables are null in the intersection of a and b, the returned value for r really only represents the consensus when a and b are distance 1 apart. */ void consensus(r, a, b) INOUT pcube r; IN register pcube a, b; { INLINEset_clear(r, cube.size); { /* Check binary variables (if any) */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ r[last] = x = a[last] & b[last]; if ((x = ~(x | x >> 1) & cube.inmask)) r[last] |= (x | (x << 1)) & (a[last] | b[last]); /* Check the full words of binary variables */ for(w = 1; w < last; w++) { r[w] = x = a[w] & b[w]; if ((x = ~(x | x >> 1) & DISJOINT)) r[w] |= (x | (x << 1)) & (a[w] | b[w]); } } } { /* Check the multiple-valued variables */ bool empty; int var; unsigned int x; register int w, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; empty = TRUE; for(w = cube.first_word[var]; w <= last; w++) if ((x = a[w] & b[w] & mask[w])) empty = FALSE, r[w] |= x; if (empty) for(w = cube.first_word[var]; w <= last; w++) r[w] |= mask[w] & (a[w] | b[w]); } } } /* cactive -- return the index of the single active variable in the cube, or return -1 if there are none or more than 2. */ int cactive(a) register pcube a; { int active = -1, dist = 0, bit_index(); { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last]; if ((x = ~ (x & x >> 1) & cube.inmask)) { if ((dist = count_ones(x)) > 1) return -1; /* more than 2 active variables */ active = (last-1)*(BPI/2) + bit_index(x) / 2; } /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w]; if ((x = ~ (x & x >> 1) & DISJOINT)) { if ((dist += count_ones(x)) > 1) return -1; /* more than 2 active variables */ active = (w-1)*(BPI/2) + bit_index(x) / 2; } } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~ a[w]) { if (++dist > 1) return -1; active = var; break; } } } return active; } /* ccommon -- return TRUE if a and b are share "active" variables active variables include variables that are empty; */ bool ccommon(a, b, cof) register pcube a, b, cof; { { /* Check binary variables */ int last; register int w; register unsigned int x, y; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] | cof[last]; y = b[last] | cof[last]; if (~(x & x>>1) & ~(y & y>>1) & cube.inmask) return TRUE; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] | cof[w]; y = b[w] | cof[w]; if (~(x & x>>1) & ~(y & y>>1) & DISJOINT) return TRUE; } } } { /* Check the multiple-valued variables */ int var; register int w, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; /* Check for some part missing from a */ for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~a[w] & ~cof[w]) { /* If so, check for some part missing from b */ for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~b[w] & ~cof[w]) return TRUE; /* both active */ break; } } } return FALSE; } /* These routines compare two sets (cubes) for the qsort() routine and return: -1 if set a is to precede set b 0 if set a and set b are equal 1 if set a is to follow set b Usually the SIZE field of the set is assumed to contain the size of the set (which will save recomputing the set size during the sort). For distance-1 merging, the global variable cube.temp[0] is a mask which mask's-out the merging variable. */ /* descend -- comparison for descending sort on set size */ int descend(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; if (SIZE(a1) > SIZE(b1)) return -1; else if (SIZE(a1) < SIZE(b1)) return 1; else { register int i = LOOP(a1); do if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; while (--i > 0); } return 0; } /* ascend -- comparison for ascending sort on set size */ int ascend(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; if (SIZE(a1) > SIZE(b1)) return 1; else if (SIZE(a1) < SIZE(b1)) return -1; else { register int i = LOOP(a1); do if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1; while (--i > 0); } return 0; } /* lex_order -- comparison for "lexical" ordering of cubes */ int lex_order(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; register int i = LOOP(a1); do if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; while (--i > 0); return 0; } /* d1_order -- comparison for distance-1 merge routine */ int d1_order(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b, c1 = cube.temp[0]; register int i = LOOP(a1); register unsigned int x1, x2; do if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1; else if (x1 < x2) return 1; while (--i > 0); return 0; } /* desc1 -- comparison (without indirection) for descending sort */ /* also has effect of handling NULL pointers,and a NULL pointer has smallest order */ int desc1(a, b) register pset a, b; { if (a == (pset) NULL) return (b == (pset) NULL) ? 0 : 1; else if (b == (pset) NULL) return -1; if (SIZE(a) > SIZE(b)) return -1; else if (SIZE(a) < SIZE(b)) return 1; else { register int i = LOOP(a); do if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1; while (--i > 0); } return 0; } ABC_NAMESPACE_IMPL_END