00001 00022 #include "ioa.h" 00023 00027 00028 /* 00029 The following is taken from the AIGER format description, 00030 which can be found at http://fmv.jku.at/aiger 00031 */ 00032 00033 00034 /* 00035 The AIGER And-Inverter Graph (AIG) Format Version 20061129 00036 ---------------------------------------------------------- 00037 Armin Biere, Johannes Kepler University, 2006 00038 00039 This report describes the AIG file format as used by the AIGER library. 00040 The purpose of this report is not only to motivate and document the 00041 format, but also to allow independent implementations of writers and 00042 readers by giving precise and unambiguous definitions. 00043 00044 ... 00045 00046 Introduction 00047 00048 The name AIGER contains as one part the acronym AIG of And-Inverter 00049 Graphs and also if pronounced in German sounds like the name of the 00050 'Eiger', a mountain in the Swiss alps. This choice should emphasize the 00051 origin of this format. It was first openly discussed at the Alpine 00052 Verification Meeting 2006 in Ascona as a way to provide a simple, compact 00053 file format for a model checking competition affiliated to CAV 2007. 00054 00055 ... 00056 00057 Binary Format Definition 00058 00059 The binary format is semantically a subset of the ASCII format with a 00060 slightly different syntax. The binary format may need to reencode 00061 literals, but translating a file in binary format into ASCII format and 00062 then back in to binary format will result in the same file. 00063 00064 The main differences of the binary format to the ASCII format are as 00065 follows. After the header the list of input literals and all the 00066 current state literals of a latch can be omitted. Furthermore the 00067 definitions of the AND gates are binary encoded. However, the symbol 00068 table and the comment section are as in the ASCII format. 00069 00070 The header of an AIGER file in binary format has 'aig' as format 00071 identifier, but otherwise is identical to the ASCII header. The standard 00072 file extension for the binary format is therefore '.aig'. 00073 00074 A header for the binary format is still in ASCII encoding: 00075 00076 aig M I L O A 00077 00078 Constants, variables and literals are handled in the same way as in the 00079 ASCII format. The first simplifying restriction is on the variable 00080 indices of inputs and latches. The variable indices of inputs come first, 00081 followed by the pseudo-primary inputs of the latches and then the variable 00082 indices of all LHS of AND gates: 00083 00084 input variable indices 1, 2, ... , I 00085 latch variable indices I+1, I+2, ... , (I+L) 00086 AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M 00087 00088 The corresponding unsigned literals are 00089 00090 input literals 2, 4, ... , 2*I 00091 latch literals 2*I+2, 2*I+4, ... , 2*(I+L) 00092 AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M 00093 00094 All literals have to be defined, and therefore 'M = I + L + A'. With this 00095 restriction it becomes possible that the inputs and the current state 00096 literals of the latches do not have to be listed explicitly. Therefore, 00097 after the header only the list of 'L' next state literals follows, one per 00098 latch on a single line, and then the 'O' outputs, again one per line. 00099 00100 In the binary format we assume that the AND gates are ordered and respect 00101 the child parent relation. AND gates with smaller literals on the LHS 00102 come first. Therefore we can assume that the literals on the right-hand 00103 side of a definition of an AND gate are smaller than the LHS literal. 00104 Furthermore we can sort the literals on the RHS, such that the larger 00105 literal comes first. A definition thus consists of three literals 00106 00107 lhs rhs0 rhs1 00108 00109 with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are 00110 pairwise different to avoid combinational self loops. Since the LHS 00111 indices of the definitions are all consecutive (as even integers), 00112 the binary format does not have to keep 'lhs'. In addition, we can use 00113 the order restriction and only write the differences 'delta0' and 'delta1' 00114 instead of 'rhs0' and 'rhs1', with 00115 00116 delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 00117 00118 The differences will all be strictly positive, and in practice often very 00119 small. We can take advantage of this fact by the simple little-endian 00120 encoding of unsigned integers of the next section. After the binary delta 00121 encoding of the RHSs of all AND gates, the optional symbol table and 00122 optional comment section start in the same format as in the ASCII case. 00123 00124 ... 00125 00126 */ 00127 00128 static unsigned Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } 00129 static unsigned Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return (unsigned)pObj->pData; } 00130 static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->pData = (void *)Num; } 00131 00132 int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); 00133 00137 00149 void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols ) 00150 { 00151 Bar_Progress_t * pProgress; 00152 FILE * pFile; 00153 Aig_Obj_t * pObj, * pDriver; 00154 int i, nNodes, Pos, nBufferSize; 00155 unsigned char * pBuffer; 00156 unsigned uLit0, uLit1, uLit; 00157 00158 // assert( Aig_ManIsStrash(pMan) ); 00159 // start the output stream 00160 pFile = fopen( pFileName, "wb" ); 00161 if ( pFile == NULL ) 00162 { 00163 fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); 00164 return; 00165 } 00166 /* 00167 Aig_ManForEachLatch( pMan, pObj, i ) 00168 if ( !Aig_LatchIsInit0(pObj) ) 00169 { 00170 fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); 00171 return; 00172 } 00173 */ 00174 // set the node numbers to be used in the output file 00175 nNodes = 0; 00176 Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); 00177 Aig_ManForEachPi( pMan, pObj, i ) 00178 Ioa_ObjSetAigerNum( pObj, nNodes++ ); 00179 Aig_ManForEachNode( pMan, pObj, i ) 00180 Ioa_ObjSetAigerNum( pObj, nNodes++ ); 00181 00182 // write the header "M I L O A" where M = I + L + A 00183 fprintf( pFile, "aig %u %u %u %u %u\n", 00184 Aig_ManPiNum(pMan) + Aig_ManNodeNum(pMan), 00185 Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan), 00186 Aig_ManRegNum(pMan), 00187 Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan), 00188 Aig_ManNodeNum(pMan) ); 00189 00190 // if the driver node is a constant, we need to complement the literal below 00191 // because, in the AIGER format, literal 0/1 is represented as number 0/1 00192 // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 00193 00194 // write latch drivers 00195 Aig_ManForEachLiSeq( pMan, pObj, i ) 00196 { 00197 pDriver = Aig_ObjFanin0(pObj); 00198 fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); 00199 } 00200 00201 // write PO drivers 00202 Aig_ManForEachPoSeq( pMan, pObj, i ) 00203 { 00204 pDriver = Aig_ObjFanin0(pObj); 00205 fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); 00206 } 00207 00208 // write the nodes into the buffer 00209 Pos = 0; 00210 nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge 00211 pBuffer = ALLOC( char, nBufferSize ); 00212 pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) ); 00213 Aig_ManForEachNode( pMan, pObj, i ) 00214 { 00215 Bar_ProgressUpdate( pProgress, i, NULL ); 00216 uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); 00217 uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); 00218 uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); 00219 assert( uLit0 < uLit1 ); 00220 Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); 00221 Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); 00222 if ( Pos > nBufferSize - 10 ) 00223 { 00224 printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); 00225 fclose( pFile ); 00226 return; 00227 } 00228 } 00229 assert( Pos < nBufferSize ); 00230 Bar_ProgressStop( pProgress ); 00231 00232 // write the buffer 00233 fwrite( pBuffer, 1, Pos, pFile ); 00234 free( pBuffer ); 00235 /* 00236 // write the symbol table 00237 if ( fWriteSymbols ) 00238 { 00239 // write PIs 00240 Aig_ManForEachPi( pMan, pObj, i ) 00241 fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) ); 00242 // write latches 00243 Aig_ManForEachLatch( pMan, pObj, i ) 00244 fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) ); 00245 // write POs 00246 Aig_ManForEachPo( pMan, pObj, i ) 00247 fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) ); 00248 } 00249 */ 00250 // write the comment 00251 fprintf( pFile, "c\n" ); 00252 if ( pMan->pName ) 00253 fprintf( pFile, ".model %s\n", pMan->pName ); 00254 fprintf( pFile, "This file was produced by the AIG package in ABC on %s\n", Ioa_TimeStamp() ); 00255 fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); 00256 fclose( pFile ); 00257 } 00258 00271 int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) 00272 { 00273 unsigned char ch; 00274 while (x & ~0x7f) 00275 { 00276 ch = (x & 0x7f) | 0x80; 00277 // putc (ch, file); 00278 pBuffer[Pos++] = ch; 00279 x >>= 7; 00280 } 00281 ch = x; 00282 // putc (ch, file); 00283 pBuffer[Pos++] = ch; 00284 return Pos; 00285 } 00286 00287 00291 00292