1 /**CFile****************************************************************
2
3 FileName [ioReadBlifMv.c]
4
5 SystemName [ABC: Logic synthesis and verification system.]
6
7 PackageName [Command processing package.]
8
9 Synopsis [Procedures to read BLIF-MV file.]
10
11 Author [Alan Mishchenko]
12
13 Affiliation [UC Berkeley]
14
15 Date [Ver. 1.0. Started - January 8, 2007.]
16
17 Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $]
18
19 ***********************************************************************/
20
21 #include "misc/zlib/zlib.h"
22 #include "misc/bzlib/bzlib.h"
23 #include "base/abc/abc.h"
24 #include "misc/vec/vecPtr.h"
25 #include "ioAbc.h"
26
27 ABC_NAMESPACE_IMPL_START
28
29 ////////////////////////////////////////////////////////////////////////
30 /// DECLARATIONS ///
31 ////////////////////////////////////////////////////////////////////////
32
33 #define IO_BLIFMV_MAXVALUES 256
34 //#define IO_VERBOSE_OUTPUT
35
36 typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var
37 typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model
38 typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager
39
40 Vec_Ptr_t *vGlobalLtlArray;
41
42 struct Io_MvVar_t_
43 {
44 int nValues; // the number of values
45 char ** pNames; // the value names
46 };
47
48 struct Io_MvMod_t_
49 {
50 // file lines
51 char * pName; // .model line
52 Vec_Ptr_t * vInputs; // .inputs lines
53 Vec_Ptr_t * vOutputs; // .outputs lines
54 Vec_Ptr_t * vLatches; // .latch lines
55 Vec_Ptr_t * vFlops; // .flop lines
56 Vec_Ptr_t * vResets; // .reset lines
57 Vec_Ptr_t * vNames; // .names lines
58 Vec_Ptr_t * vSubckts; // .subckt lines
59 Vec_Ptr_t * vShorts; // .short lines
60 Vec_Ptr_t * vOnehots; // .onehot lines
61 Vec_Ptr_t * vMvs; // .mv lines
62 Vec_Ptr_t * vConstrs; // .constraint lines
63 Vec_Ptr_t * vLtlProperties;
64 int fBlackBox; // indicates blackbox model
65 // the resulting network
66 Abc_Ntk_t * pNtk;
67 Abc_Obj_t * pResetLatch;
68 // the parent manager
69 Io_MvMan_t * pMan;
70 };
71
72 struct Io_MvMan_t_
73 {
74 // general info about file
75 int fBlifMv; // the file is BLIF-MV
76 int fUseReset; // the reset circuitry is added
77 char * pFileName; // the name of the file
78 char * pBuffer; // the contents of the file
79 Vec_Ptr_t * vLines; // the line beginnings
80 // the results of reading
81 Abc_Des_t * pDesign; // the design under construction
82 int nNDnodes; // the counter of ND nodes
83 // intermediate storage for models
84 Vec_Ptr_t * vModels; // vector of models
85 Io_MvMod_t * pLatest; // the current model
86 // current processing info
87 Vec_Ptr_t * vTokens; // the current tokens
88 Vec_Ptr_t * vTokens2; // the current tokens
89 Vec_Str_t * vFunc; // the local function
90 // error reporting
91 char sError[512]; // the error string generated during parsing
92 // statistics
93 int nTablesRead; // the number of processed tables
94 int nTablesLeft; // the number of dangling tables
95 };
96
97 // static functions
98 static Io_MvMan_t * Io_MvAlloc();
99 static void Io_MvFree( Io_MvMan_t * p );
100 static Io_MvMod_t * Io_MvModAlloc();
101 static void Io_MvModFree( Io_MvMod_t * p );
102 static char * Io_MvLoadFile( char * pFileName );
103 static void Io_MvReadPreparse( Io_MvMan_t * p );
104 static int Io_MvReadInterfaces( Io_MvMan_t * p );
105 static Abc_Des_t * Io_MvParse( Io_MvMan_t * p );
106 static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine );
107 static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine );
108 static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine );
109 static int Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine );
110 static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine );
111 static int Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine );
112 static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine );
113 static Vec_Int_t * Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine );
114 static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
115 static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
116 static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
117 static int Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine );
118 static int Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine );
119 static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
120 static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
121
Io_MvCharIsSpace(char s)122 static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
Io_MvCharIsMvSymb(char s)123 static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; }
124
125 extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
126
127 ////////////////////////////////////////////////////////////////////////
128 /// FUNCTION DEFINITIONS ///
129 ////////////////////////////////////////////////////////////////////////
130
131 /**Function*************************************************************
132
133 Synopsis [Reads the network from the BLIF or BLIF-MV file.]
134
135 Description []
136
137 SideEffects []
138
139 SeeAlso []
140
141 ***********************************************************************/
Io_ReadBlifMv(char * pFileName,int fBlifMv,int fCheck)142 Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
143 {
144 FILE * pFile;
145 Io_MvMan_t * p;
146 Abc_Ntk_t * pNtk, * pExdc;
147 Abc_Des_t * pDesign = NULL;
148 char * pDesignName;
149 int RetValue, i;
150 char * pLtlProp;
151
152 // check that the file is available
153 pFile = fopen( pFileName, "rb" );
154 if ( pFile == NULL )
155 {
156 printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" );
157 return 0;
158 }
159 fclose( pFile );
160
161 // start the file reader
162 p = Io_MvAlloc();
163 p->fBlifMv = fBlifMv;
164 p->fUseReset = 1;
165 p->pFileName = pFileName;
166 p->pBuffer = Io_MvLoadFile( pFileName );
167 if ( p->pBuffer == NULL )
168 {
169 Io_MvFree( p );
170 return NULL;
171 }
172 // set the design name
173 pDesignName = Extra_FileNameGeneric( pFileName );
174 p->pDesign = Abc_DesCreate( pDesignName );
175 ABC_FREE( pDesignName );
176 // free the HOP manager
177 Hop_ManStop( (Hop_Man_t *)p->pDesign->pManFunc );
178 p->pDesign->pManFunc = NULL;
179 // prepare the file for parsing
180 Io_MvReadPreparse( p );
181 // parse interfaces of each network and construct the network
182 if ( Io_MvReadInterfaces( p ) )
183 pDesign = Io_MvParse( p );
184 if ( p->sError[0] )
185 fprintf( stdout, "%s\n", p->sError );
186 Io_MvFree( p );
187 if ( pDesign == NULL )
188 return NULL;
189 // pDesign should be linked to all models of the design
190
191 // make sure that everything is okay with the network structure
192 if ( fCheck )
193 {
194 Vec_PtrForEachEntry( Abc_Ntk_t *, pDesign->vModules, pNtk, i )
195 {
196 if ( !Abc_NtkCheckRead( pNtk ) )
197 {
198 printf( "Io_ReadBlifMv: The network check has failed for model %s.\n", pNtk->pName );
199 Abc_DesFree( pDesign, NULL );
200 return NULL;
201 }
202 }
203 }
204
205 //Abc_DesPrint( pDesign );
206
207 // check if there is an EXDC network
208 if ( Vec_PtrSize(pDesign->vModules) > 1 )
209 {
210 pNtk = (Abc_Ntk_t *)Vec_PtrEntry(pDesign->vModules, 0);
211 Vec_PtrForEachEntryStart( Abc_Ntk_t *, pDesign->vModules, pExdc, i, 1 )
212 if ( !strcmp(pExdc->pName, "EXDC") )
213 {
214 assert( pNtk->pExdc == NULL );
215 pNtk->pExdc = pExdc;
216 Vec_PtrRemove(pDesign->vModules, pExdc);
217 pExdc->pDesign = NULL;
218 i--;
219 }
220 else
221 pNtk = pExdc;
222 }
223
224 // detect top-level model
225 RetValue = Abc_DesFindTopLevelModels( pDesign );
226 pNtk = (Abc_Ntk_t *)Vec_PtrEntry( pDesign->vTops, 0 );
227 if ( RetValue > 1 )
228 printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
229 Vec_PtrSize(pDesign->vTops), pNtk->pName );
230
231 // extract the master network
232 pNtk->pDesign = pDesign;
233 pDesign->pManFunc = NULL;
234
235 // verify the design for cyclic dependence
236 assert( Vec_PtrSize(pDesign->vModules) > 0 );
237 if ( Vec_PtrSize(pDesign->vModules) == 1 )
238 {
239 // printf( "Warning: The design is not hierarchical.\n" );
240 Abc_DesFree( pDesign, pNtk );
241 pNtk->pDesign = NULL;
242 pNtk->pSpec = Extra_UtilStrsav( pFileName );
243 }
244 else
245 Abc_NtkIsAcyclicHierarchy( pNtk );
246
247 //Io_WriteBlifMv( pNtk, "_temp_.mv" );
248 if ( pNtk->pSpec == NULL )
249 pNtk->pSpec = Extra_UtilStrsav( pFileName );
250
251 vGlobalLtlArray = Vec_PtrAlloc( 100 );
252 Vec_PtrForEachEntry( char *, vGlobalLtlArray, pLtlProp, i )
253 Vec_PtrPush( pNtk->vLtlProperties, pLtlProp );
254 Vec_PtrFreeP( &vGlobalLtlArray );
255 return pNtk;
256 }
257
258 /**Function*************************************************************
259
260 Synopsis [Allocates the BLIF parsing structure.]
261
262 Description []
263
264 SideEffects []
265
266 SeeAlso []
267
268 ***********************************************************************/
Io_MvAlloc()269 static Io_MvMan_t * Io_MvAlloc()
270 {
271 Io_MvMan_t * p;
272 p = ABC_ALLOC( Io_MvMan_t, 1 );
273 memset( p, 0, sizeof(Io_MvMan_t) );
274 p->vLines = Vec_PtrAlloc( 512 );
275 p->vModels = Vec_PtrAlloc( 512 );
276 p->vTokens = Vec_PtrAlloc( 512 );
277 p->vTokens2 = Vec_PtrAlloc( 512 );
278 p->vFunc = Vec_StrAlloc( 512 );
279 return p;
280 }
281
282 /**Function*************************************************************
283
284 Synopsis [Frees the BLIF parsing structure.]
285
286 Description []
287
288 SideEffects []
289
290 SeeAlso []
291
292 ***********************************************************************/
Io_MvFree(Io_MvMan_t * p)293 static void Io_MvFree( Io_MvMan_t * p )
294 {
295 Io_MvMod_t * pMod;
296 int i;
297 if ( p->pDesign )
298 Abc_DesFree( p->pDesign, NULL );
299 if ( p->pBuffer )
300 ABC_FREE( p->pBuffer );
301 if ( p->vLines )
302 Vec_PtrFree( p->vLines );
303 if ( p->vModels )
304 {
305 Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
306 Io_MvModFree( pMod );
307 Vec_PtrFree( p->vModels );
308 }
309 Vec_PtrFree( p->vTokens );
310 Vec_PtrFree( p->vTokens2 );
311 Vec_StrFree( p->vFunc );
312 ABC_FREE( p );
313 }
314
315 /**Function*************************************************************
316
317 Synopsis [Allocates the BLIF parsing structure for one model.]
318
319 Description []
320
321 SideEffects []
322
323 SeeAlso []
324
325 ***********************************************************************/
Io_MvModAlloc()326 static Io_MvMod_t * Io_MvModAlloc()
327 {
328 Io_MvMod_t * p;
329 p = ABC_ALLOC( Io_MvMod_t, 1 );
330 memset( p, 0, sizeof(Io_MvMod_t) );
331 p->vInputs = Vec_PtrAlloc( 512 );
332 p->vOutputs = Vec_PtrAlloc( 512 );
333 p->vLatches = Vec_PtrAlloc( 512 );
334 p->vFlops = Vec_PtrAlloc( 512 );
335 p->vResets = Vec_PtrAlloc( 512 );
336 p->vNames = Vec_PtrAlloc( 512 );
337 p->vSubckts = Vec_PtrAlloc( 512 );
338 p->vShorts = Vec_PtrAlloc( 512 );
339 p->vOnehots = Vec_PtrAlloc( 512 );
340 p->vMvs = Vec_PtrAlloc( 512 );
341 p->vConstrs = Vec_PtrAlloc( 512 );
342 p->vLtlProperties = Vec_PtrAlloc( 512 );
343 return p;
344 }
345
346 /**Function*************************************************************
347
348 Synopsis [Allocates the BLIF parsing structure for one model.]
349
350 Description []
351
352 SideEffects []
353
354 SeeAlso []
355
356 ***********************************************************************/
Io_MvModFree(Io_MvMod_t * p)357 static void Io_MvModFree( Io_MvMod_t * p )
358 {
359 // if ( p->pNtk )
360 // Abc_NtkDelete( p->pNtk );
361 Vec_PtrFree( p->vLtlProperties );
362 Vec_PtrFree( p->vInputs );
363 Vec_PtrFree( p->vOutputs );
364 Vec_PtrFree( p->vLatches );
365 Vec_PtrFree( p->vFlops );
366 Vec_PtrFree( p->vResets );
367 Vec_PtrFree( p->vNames );
368 Vec_PtrFree( p->vSubckts );
369 Vec_PtrFree( p->vShorts );
370 Vec_PtrFree( p->vOnehots );
371 Vec_PtrFree( p->vMvs );
372 Vec_PtrFree( p->vConstrs );
373 ABC_FREE( p );
374 }
375
376
377
378 /**Function*************************************************************
379
380 Synopsis [Counts the number of given chars.]
381
382 Description []
383
384 SideEffects []
385
386 SeeAlso []
387
388 ***********************************************************************/
Io_MvCountChars(char * pLine,char Char)389 static int Io_MvCountChars( char * pLine, char Char )
390 {
391 char * pCur;
392 int Counter = 0;
393 for ( pCur = pLine; *pCur; pCur++ )
394 if ( *pCur == Char )
395 Counter++;
396 return Counter;
397 }
398
399 /**Function*************************************************************
400
401 Synopsis [Returns the place where the arrow is hiding.]
402
403 Description []
404
405 SideEffects []
406
407 SeeAlso []
408
409 ***********************************************************************/
Io_MvFindArrow(char * pLine)410 static char * Io_MvFindArrow( char * pLine )
411 {
412 char * pCur;
413 for ( pCur = pLine; *(pCur+1); pCur++ )
414 if ( *pCur == '-' && *(pCur+1) == '>' )
415 {
416 *pCur = ' ';
417 *(pCur+1) = ' ';
418 return pCur;
419 }
420 return NULL;
421 }
422
423 /**Function*************************************************************
424
425 Synopsis [Collects the already split tokens.]
426
427 Description []
428
429 SideEffects []
430
431 SeeAlso []
432
433 ***********************************************************************/
Io_MvCollectTokens(Vec_Ptr_t * vTokens,char * pInput,char * pOutput)434 static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
435 {
436 char * pCur;
437 Vec_PtrClear( vTokens );
438 for ( pCur = pInput; pCur < pOutput; pCur++ )
439 {
440 if ( *pCur == 0 )
441 continue;
442 Vec_PtrPush( vTokens, pCur );
443 while ( *++pCur );
444 }
445 }
446
447 /**Function*************************************************************
448
449 Synopsis [Splits the line into tokens.]
450
451 Description []
452
453 SideEffects []
454
455 SeeAlso []
456
457 ***********************************************************************/
Io_MvSplitIntoTokens(Vec_Ptr_t * vTokens,char * pLine,char Stop)458 static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
459 {
460 char * pCur;
461 // clear spaces
462 for ( pCur = pLine; *pCur != Stop; pCur++ )
463 if ( Io_MvCharIsSpace(*pCur) )
464 *pCur = 0;
465 // collect tokens
466 Io_MvCollectTokens( vTokens, pLine, pCur );
467 }
468
469 /**Function*************************************************************
470
471 Synopsis [Splits the line into tokens when .default may be present.]
472
473 Description []
474
475 SideEffects []
476
477 SeeAlso []
478
479 ***********************************************************************/
Io_MvSplitIntoTokensMv(Vec_Ptr_t * vTokens,char * pLine)480 static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine )
481 {
482 char * pCur;
483 // clear spaces
484 for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ )
485 if ( Io_MvCharIsSpace(*pCur) )
486 *pCur = 0;
487 // collect tokens
488 Io_MvCollectTokens( vTokens, pLine, pCur );
489 }
490
491 /**Function*************************************************************
492
493 Synopsis [Splits the line into tokens.]
494
495 Description []
496
497 SideEffects []
498
499 SeeAlso []
500
501 ***********************************************************************/
Io_MvSplitIntoTokensAndClear(Vec_Ptr_t * vTokens,char * pLine,char Stop,char Char)502 static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
503 {
504 char * pCur;
505 // clear spaces
506 for ( pCur = pLine; *pCur != Stop; pCur++ )
507 if ( Io_MvCharIsSpace(*pCur) || *pCur == Char )
508 *pCur = 0;
509 // collect tokens
510 Io_MvCollectTokens( vTokens, pLine, pCur );
511 }
512
513 /**Function*************************************************************
514
515 Synopsis [Returns the 1-based number of the line in which the token occurs.]
516
517 Description []
518
519 SideEffects []
520
521 SeeAlso []
522
523 ***********************************************************************/
Io_MvGetLine(Io_MvMan_t * p,char * pToken)524 static int Io_MvGetLine( Io_MvMan_t * p, char * pToken )
525 {
526 char * pLine;
527 int i;
528 Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
529 if ( pToken < pLine )
530 return i;
531 return -1;
532 }
533
534 /**Function*************************************************************
535
536 Synopsis [Reads the file into a character buffer.]
537
538 Description []
539
540 SideEffects []
541
542 SeeAlso []
543
544 ***********************************************************************/
545 typedef struct buflist {
546 char buf[1<<20];
547 int nBuf;
548 struct buflist * next;
549 } buflist;
550
Io_MvLoadFileBz2(char * pFileName,int * pnFileSize)551 char * Io_MvLoadFileBz2( char * pFileName, int * pnFileSize )
552 {
553 FILE * pFile;
554 int nFileSize = 0;
555 char * pContents;
556 BZFILE * b;
557 int bzError, RetValue;
558 struct buflist * pNext;
559 buflist * bufHead = NULL, * buf = NULL;
560
561 pFile = fopen( pFileName, "rb" );
562 if ( pFile == NULL )
563 {
564 Abc_Print( -1, "Io_MvLoadFileBz2(): The file is unavailable (absent or open).\n" );
565 return NULL;
566 }
567 b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0);
568 if (bzError != BZ_OK) {
569 Abc_Print( -1, "Io_MvLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError );
570 return NULL;
571 }
572 do {
573 if (!bufHead)
574 buf = bufHead = ABC_ALLOC( buflist, 1 );
575 else
576 buf = buf->next = ABC_ALLOC( buflist, 1 );
577 nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20);
578 buf->next = NULL;
579 } while (bzError == BZ_OK);
580 if (bzError == BZ_STREAM_END) {
581 // we're okay
582 char * p;
583 int nBytes = 0;
584 BZ2_bzReadClose(&bzError,b);
585 p = pContents = ABC_ALLOC( char, nFileSize + 10 );
586 buf = bufHead;
587 do {
588 memcpy(p+nBytes,buf->buf,(size_t)buf->nBuf);
589 nBytes += buf->nBuf;
590 // } while((buf = buf->next));
591 pNext = buf->next;
592 ABC_FREE( buf );
593 } while((buf = pNext));
594 } else if (bzError == BZ_DATA_ERROR_MAGIC) {
595 // not a BZIP2 file
596 BZ2_bzReadClose(&bzError,b);
597 fseek( pFile, 0, SEEK_END );
598 nFileSize = ftell( pFile );
599 if ( nFileSize == 0 )
600 {
601 Abc_Print( -1, "Io_MvLoadFileBz2(): The file is empty.\n" );
602 return NULL;
603 }
604 pContents = ABC_ALLOC( char, nFileSize + 10 );
605 rewind( pFile );
606 RetValue = fread( pContents, nFileSize, 1, pFile );
607 } else {
608 // Some other error.
609 Abc_Print( -1, "Io_MvLoadFileBz2(): Unable to read the compressed BLIF.\n" );
610 return NULL;
611 }
612 fclose( pFile );
613 // finish off the file with the spare .end line
614 // some benchmarks suddenly break off without this line
615 strcpy( pContents + nFileSize, "\n.end\n" );
616 *pnFileSize = nFileSize;
617 return pContents;
618 }
619
620 /**Function*************************************************************
621
622 Synopsis [Reads the file into a character buffer.]
623
624 Description []
625
626 SideEffects []
627
628 SeeAlso []
629
630 ***********************************************************************/
Io_MvLoadFileGz(char * pFileName,int * pnFileSize)631 static char * Io_MvLoadFileGz( char * pFileName, int * pnFileSize )
632 {
633 const int READ_BLOCK_SIZE = 100000;
634 gzFile pFile;
635 char * pContents;
636 int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE;
637 pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen
638 pContents = ABC_ALLOC( char, nFileSize );
639 readBlock = 0;
640 while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) {
641 //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead);
642 nFileSize += READ_BLOCK_SIZE;
643 pContents = ABC_REALLOC(char, pContents, nFileSize);
644 ++readBlock;
645 }
646 //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead);
647 assert( amtRead != -1 ); // indicates a zlib error
648 nFileSize -= (READ_BLOCK_SIZE - amtRead);
649 gzclose(pFile);
650 *pnFileSize = nFileSize;
651 return pContents;
652 }
653
654 /**Function*************************************************************
655
656 Synopsis [Reads the file into a character buffer.]
657
658 Description []
659
660 SideEffects []
661
662 SeeAlso []
663
664 ***********************************************************************/
Io_MvLoadFile(char * pFileName)665 static char * Io_MvLoadFile( char * pFileName )
666 {
667 FILE * pFile;
668 int nFileSize;
669 char * pContents;
670 int RetValue;
671 if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) )
672 return Io_MvLoadFileBz2( pFileName, &nFileSize );
673 if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) )
674 return Io_MvLoadFileGz( pFileName, &nFileSize );
675 pFile = fopen( pFileName, "rb" );
676 if ( pFile == NULL )
677 {
678 printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" );
679 return NULL;
680 }
681 fseek( pFile, 0, SEEK_END );
682 nFileSize = ftell( pFile );
683 if ( nFileSize == 0 )
684 {
685 fclose( pFile );
686 printf( "Io_MvLoadFile(): The file is empty.\n" );
687 return NULL;
688 }
689 pContents = ABC_ALLOC( char, nFileSize + 10 );
690 rewind( pFile );
691 RetValue = fread( pContents, nFileSize, 1, pFile );
692 fclose( pFile );
693 // finish off the file with the spare .end line
694 // some benchmarks suddenly break off without this line
695 strcpy( pContents + nFileSize, "\n.end\n" );
696 return pContents;
697 }
698
699 /**Function*************************************************************
700
701 Synopsis [Prepares the parsing.]
702
703 Description [Performs several preliminary operations:
704 - Cuts the file buffer into separate lines.
705 - Removes comments and line extenders.
706 - Sorts lines by directives.
707 - Estimates the number of objects.
708 - Allocates room for the objects.
709 - Allocates room for the hash table.]
710
711 SideEffects []
712
713 SeeAlso []
714
715 ***********************************************************************/
Io_MvReadPreparse(Io_MvMan_t * p)716 static void Io_MvReadPreparse( Io_MvMan_t * p )
717 {
718 char * pCur, * pPrev;
719 int i, fComment = 0;
720 // parse the buffer into lines and remove comments
721 Vec_PtrPush( p->vLines, p->pBuffer );
722 for ( pCur = p->pBuffer; *pCur; pCur++ )
723 {
724 if ( *pCur == '\n' )
725 {
726 *pCur = 0;
727 // if ( *(pCur-1) == '\r' )
728 // *(pCur-1) = 0;
729 fComment = 0;
730 Vec_PtrPush( p->vLines, pCur + 1 );
731 }
732 else if ( *pCur == '#' )
733 fComment = 1;
734 // remove comments
735 if ( fComment )
736 *pCur = 0;
737 }
738
739 // unfold the line extensions and sort lines by directive
740 Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
741 {
742 if ( *pCur == 0 )
743 continue;
744 // find previous non-space character
745 for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
746 if ( !Io_MvCharIsSpace(*pPrev) )
747 break;
748 // if it is the line extender, overwrite it with spaces
749 if ( pPrev >= p->pBuffer && *pPrev == '\\' )
750 {
751 for ( ; *pPrev; pPrev++ )
752 *pPrev = ' ';
753 *pPrev = ' ';
754 continue;
755 }
756 // skip spaces at the beginning of the line
757 while ( Io_MvCharIsSpace(*pCur++) );
758 // parse directives
759 if ( *(pCur-1) != '.' )
760 continue;
761 if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) )
762 Vec_PtrPush( p->pLatest->vNames, pCur );
763 else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) )
764 continue;
765 else if ( !strncmp( pCur, "ltlformula", 10 ) )
766 Vec_PtrPush( p->pLatest->vLtlProperties, pCur );
767 else if ( !strncmp(pCur, "latch", 5) )
768 Vec_PtrPush( p->pLatest->vLatches, pCur );
769 else if ( !strncmp(pCur, "flop", 4) )
770 Vec_PtrPush( p->pLatest->vFlops, pCur );
771 else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) )
772 Vec_PtrPush( p->pLatest->vResets, pCur );
773 else if ( !strncmp(pCur, "inputs", 6) )
774 Vec_PtrPush( p->pLatest->vInputs, pCur );
775 else if ( !strncmp(pCur, "outputs", 7) )
776 Vec_PtrPush( p->pLatest->vOutputs, pCur );
777 else if ( !strncmp(pCur, "subckt", 6) )
778 Vec_PtrPush( p->pLatest->vSubckts, pCur );
779 else if ( !strncmp(pCur, "short", 5) )
780 Vec_PtrPush( p->pLatest->vShorts, pCur );
781 else if ( !strncmp(pCur, "onehot", 6) )
782 Vec_PtrPush( p->pLatest->vOnehots, pCur );
783 else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) )
784 Vec_PtrPush( p->pLatest->vMvs, pCur );
785 else if ( !strncmp(pCur, "constraint", 10) )
786 Vec_PtrPush( p->pLatest->vConstrs, pCur );
787 else if ( !strncmp(pCur, "blackbox", 8) )
788 p->pLatest->fBlackBox = 1;
789 else if ( !strncmp(pCur, "model", 5) )
790 {
791 p->pLatest = Io_MvModAlloc();
792 p->pLatest->pName = pCur;
793 p->pLatest->pMan = p;
794 }
795 else if ( !strncmp(pCur, "end", 3) )
796 {
797 if ( p->pLatest )
798 Vec_PtrPush( p->vModels, p->pLatest );
799 p->pLatest = NULL;
800 }
801 else if ( !strncmp(pCur, "exdc", 4) )
802 {
803 // fprintf( stdout, "Line %d: The design contains EXDC network (warning only).\n", Io_MvGetLine(p, pCur) );
804 fprintf( stdout, "Warning: The design contains EXDC network.\n" );
805 if ( p->pLatest )
806 Vec_PtrPush( p->vModels, p->pLatest );
807 p->pLatest = Io_MvModAlloc();
808 p->pLatest->pName = NULL;
809 p->pLatest->pMan = p;
810 }
811 else if ( !strncmp(pCur, "attrib", 6) )
812 {}
813 else if ( !strncmp(pCur, "delay", 5) )
814 {}
815 else if ( !strncmp(pCur, "input_", 6) )
816 {}
817 else if ( !strncmp(pCur, "output_", 7) )
818 {}
819 else if ( !strncmp(pCur, "no_merge", 8) )
820 {}
821 else if ( !strncmp(pCur, "wd", 2) )
822 {}
823 // else if ( !strncmp(pCur, "inouts", 6) )
824 // {}
825 else
826 {
827 pCur--;
828 if ( pCur[strlen(pCur)-1] == '\r' )
829 pCur[strlen(pCur)-1] = 0;
830 fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur );
831 }
832 }
833 }
834
835 /**Function*************************************************************
836
837 Synopsis [Parses interfaces of the models.]
838
839 Description []
840
841 SideEffects []
842
843 SeeAlso []
844
845 ***********************************************************************/
Io_MvReadInterfaces(Io_MvMan_t * p)846 static int Io_MvReadInterfaces( Io_MvMan_t * p )
847 {
848 Io_MvMod_t * pMod;
849 char * pLine;
850 int i, k, nOutsOld;
851 // iterate through the models
852 Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
853 {
854 // parse the model
855 if ( !Io_MvParseLineModel( pMod, pMod->pName ) )
856 return 0;
857 // add model to the design
858 if ( !Abc_DesAddModel( p->pDesign, pMod->pNtk ) )
859 {
860 sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName );
861 return 0;
862 }
863 // parse the inputs
864 Vec_PtrForEachEntry( char *, pMod->vInputs, pLine, k )
865 if ( !Io_MvParseLineInputs( pMod, pLine ) )
866 return 0;
867 // parse the outputs
868 Vec_PtrForEachEntry( char *, pMod->vOutputs, pLine, k )
869 if ( !Io_MvParseLineOutputs( pMod, pLine ) )
870 return 0;
871 // parse the constraints
872 nOutsOld = Abc_NtkPoNum(pMod->pNtk);
873 Vec_PtrForEachEntry( char *, pMod->vConstrs, pLine, k )
874 if ( !Io_MvParseLineConstrs( pMod, pLine ) )
875 return 0;
876 pMod->pNtk->nConstrs = Abc_NtkPoNum(pMod->pNtk) - nOutsOld;
877 Vec_PtrForEachEntry( char *, pMod->vLtlProperties, pLine, k )
878 if ( !Io_MvParseLineLtlProperty( pMod, pLine ) )
879 return 0;
880 // report the results
881 #ifdef IO_VERBOSE_OUTPUT
882 if ( Vec_PtrSize(p->vModels) > 1 )
883 printf( "Parsed %-32s: PI =%6d PO =%6d ND =%8d FF =%6d B =%6d\n",
884 pMod->pNtk->pName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkPoNum(pMod->pNtk),
885 Vec_PtrSize(pMod->vNames), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vSubckts) );
886 #endif
887 }
888 return 1;
889 }
890
891
892 /**Function*************************************************************
893
894 Synopsis []
895
896 Description []
897
898 SideEffects []
899
900 SeeAlso []
901
902 ***********************************************************************/
Io_MvParse(Io_MvMan_t * p)903 static Abc_Des_t * Io_MvParse( Io_MvMan_t * p )
904 {
905 Abc_Des_t * pDesign;
906 Io_MvMod_t * pMod;
907 char * pLine;
908 int i, k;
909 // iterate through the models
910 Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
911 {
912 #ifdef IO_VERBOSE_OUTPUT
913 if ( Vec_PtrSize(p->vModels) > 1 )
914 printf( "Parsing model %s...\n", pMod->pNtk->pName );
915 #endif
916
917 // check if there any MV lines
918 if ( Vec_PtrSize(pMod->vMvs) > 0 )
919 Abc_NtkStartMvVars( pMod->pNtk );
920 // parse the mv lines
921 Vec_PtrForEachEntry( char *, pMod->vMvs, pLine, k )
922 if ( !Io_MvParseLineMv( pMod, pLine ) )
923 return NULL;
924 // if reset lines are used there should be the same number of them as latches
925 if ( Vec_PtrSize(pMod->vResets) > 0 )
926 {
927 if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) )
928 {
929 sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).",
930 Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) );
931 return NULL;
932 }
933 // create binary latch with 1-data and 0-init
934 if ( p->fUseReset )
935 pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
936 }
937 // parse the flops
938 Vec_PtrForEachEntry( char *, pMod->vFlops, pLine, k )
939 if ( !Io_MvParseLineFlop( pMod, pLine ) )
940 return NULL;
941 // parse the latches
942 Vec_PtrForEachEntry( char *, pMod->vLatches, pLine, k )
943 if ( !Io_MvParseLineLatch( pMod, pLine ) )
944 return NULL;
945 // parse the reset lines
946 if ( p->fUseReset )
947 Vec_PtrForEachEntry( char *, pMod->vResets, pLine, k )
948 if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
949 return NULL;
950 // parse the nodes
951 if ( p->fBlifMv )
952 {
953 Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k )
954 if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) )
955 return NULL;
956 }
957 else
958 {
959 Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k )
960 if ( !Io_MvParseLineNamesBlif( pMod, pLine ) )
961 return NULL;
962 Vec_PtrForEachEntry( char *, pMod->vShorts, pLine, k )
963 if ( !Io_MvParseLineShortBlif( pMod, pLine ) )
964 return NULL;
965 }
966 // parse the subcircuits
967 Vec_PtrForEachEntry( char *, pMod->vSubckts, pLine, k )
968 if ( !Io_MvParseLineSubckt( pMod, pLine ) )
969 return NULL;
970
971 // allow for blackboxes without .blackbox line
972 if ( Abc_NtkLatchNum(pMod->pNtk) == 0 && Abc_NtkNodeNum(pMod->pNtk) == 0 && Abc_NtkBoxNum(pMod->pNtk) == 0 )
973 {
974 if ( pMod->pNtk->ntkFunc == ABC_FUNC_SOP )
975 {
976 Mem_FlexStop( (Mem_Flex_t *)pMod->pNtk->pManFunc, 0 );
977 pMod->pNtk->pManFunc = NULL;
978 pMod->pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
979 }
980 }
981
982 // finalize the network
983 Abc_NtkFinalizeRead( pMod->pNtk );
984 // read the one-hotness lines
985 if ( Vec_PtrSize(pMod->vOnehots) > 0 )
986 {
987 Vec_Int_t * vLine;
988 Abc_Obj_t * pObj;
989 // set register numbers
990 Abc_NtkForEachLatch( pMod->pNtk, pObj, k )
991 pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)k;
992 // derive register
993 pMod->pNtk->vOnehots = Vec_PtrAlloc( Vec_PtrSize(pMod->vOnehots) );
994 Vec_PtrForEachEntry( char *, pMod->vOnehots, pLine, k )
995 {
996 vLine = Io_MvParseLineOnehot( pMod, pLine );
997 if ( vLine == NULL )
998 return NULL;
999 Vec_PtrPush( pMod->pNtk->vOnehots, vLine );
1000 // printf( "Parsed %d one-hot registers.\n", Vec_IntSize(vLine) );
1001 }
1002 // reset register numbers
1003 Abc_NtkForEachLatch( pMod->pNtk, pObj, k )
1004 pObj->pNext = NULL;
1005 // print the result
1006 printf( "Parsed %d groups of 1-hot registers: { ", Vec_PtrSize(pMod->pNtk->vOnehots) );
1007 Vec_PtrForEachEntry( Vec_Int_t *, pMod->pNtk->vOnehots, vLine, k )
1008 printf( "%d ", Vec_IntSize(vLine) );
1009 printf( "}\n" );
1010 printf( "The total number of 1-hot registers = %d. (%.2f %%)\n",
1011 Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ),
1012 100.0 * Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ) / Abc_NtkLatchNum(pMod->pNtk) );
1013 {
1014 extern void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * vOnehots );
1015 char * pFileName = Extra_FileNameGenericAppend( pMod->pMan->pFileName, "_1h.blif" );
1016 Abc_GenOneHotIntervals( pFileName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkLatchNum(pMod->pNtk), pMod->pNtk->vOnehots );
1017 printf( "One-hotness condition is written into file \"%s\".\n", pFileName );
1018 }
1019 }
1020 if ( Vec_PtrSize(pMod->vFlops) )
1021 {
1022 printf( "Warning: The parser converted %d .flop lines into .latch lines\n", Vec_PtrSize(pMod->vFlops) );
1023 printf( "(information about set, reset, enable of the flops may be lost).\n" );
1024 }
1025
1026 }
1027 if ( p->nNDnodes )
1028 // printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes );
1029 printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
1030 // return the network
1031 pDesign = p->pDesign;
1032 p->pDesign = NULL;
1033 return pDesign;
1034 }
1035
1036 /**Function*************************************************************
1037
1038 Synopsis [Parses the model line.]
1039
1040 Description []
1041
1042 SideEffects []
1043
1044 SeeAlso []
1045
1046 ***********************************************************************/
Io_MvParseLineModel(Io_MvMod_t * p,char * pLine)1047 static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine )
1048 {
1049 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1050 char * pToken, * pPivot;
1051 if ( pLine == NULL )
1052 {
1053 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
1054 p->pNtk->pName = Extra_UtilStrsav( "EXDC" );
1055 return 1;
1056 }
1057 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1058 pToken = (char *)Vec_PtrEntry( vTokens, 0 );
1059 assert( !strcmp(pToken, "model") );
1060 if ( Vec_PtrSize(vTokens) != 2 )
1061 {
1062 sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
1063 return 0;
1064 }
1065 if ( p->fBlackBox )
1066 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 );
1067 else if ( p->pMan->fBlifMv )
1068 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 );
1069 else
1070 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
1071 // for ( pPivot = pToken = Vec_PtrEntry(vTokens, 1); *pToken; pToken++ )
1072 // if ( *pToken == '/' || *pToken == '\\' )
1073 // pPivot = pToken+1;
1074 pPivot = pToken = (char *)Vec_PtrEntry(vTokens, 1);
1075 p->pNtk->pName = Extra_UtilStrsav( pPivot );
1076 return 1;
1077 }
1078
1079 /**Function*************************************************************
1080
1081 Synopsis [Parses the inputs line.]
1082
1083 Description []
1084
1085 SideEffects []
1086
1087 SeeAlso []
1088
1089 ***********************************************************************/
Io_MvParseLineInputs(Io_MvMod_t * p,char * pLine)1090 static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine )
1091 {
1092 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1093 char * pToken;
1094 int i;
1095 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1096 pToken = (char *)Vec_PtrEntry(vTokens, 0);
1097 assert( !strcmp(pToken, "inputs") );
1098 Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
1099 Io_ReadCreatePi( p->pNtk, pToken );
1100 return 1;
1101 }
1102
1103 /**Function*************************************************************
1104
1105 Synopsis [Parses the outputs line.]
1106
1107 Description []
1108
1109 SideEffects []
1110
1111 SeeAlso []
1112
1113 ***********************************************************************/
Io_MvParseLineOutputs(Io_MvMod_t * p,char * pLine)1114 static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
1115 {
1116 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1117 char * pToken;
1118 int i;
1119 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1120 pToken = (char *)Vec_PtrEntry(vTokens, 0);
1121 assert( !strcmp(pToken, "outputs") );
1122 Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
1123 Io_ReadCreatePo( p->pNtk, pToken );
1124 return 1;
1125 }
1126
1127 /**Function*************************************************************
1128
1129 Synopsis [Parses the outputs line.]
1130
1131 Description []
1132
1133 SideEffects []
1134
1135 SeeAlso []
1136
1137 ***********************************************************************/
Io_MvParseLineConstrs(Io_MvMod_t * p,char * pLine)1138 static int Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine )
1139 {
1140 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1141 char * pToken;
1142 int i;
1143 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1144 pToken = (char *)Vec_PtrEntry(vTokens, 0);
1145 assert( !strcmp(pToken, "constraint") );
1146 Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
1147 Io_ReadCreatePo( p->pNtk, pToken );
1148 return 1;
1149 }
1150
1151 /**Function*************************************************************
1152
1153 Synopsis [Parses the LTL property line.]
1154
1155 Description []
1156
1157 SideEffects []
1158
1159 SeeAlso []
1160
1161 ***********************************************************************/
Io_MvParseLineLtlProperty(Io_MvMod_t * p,char * pLine)1162 static int Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine )
1163 {
1164 int i, j;
1165 int quoteBegin, quoteEnd;
1166 char keyWordLtlFormula[11];
1167 char *actualLtlFormula;
1168
1169 //checking if the line begins with the keyword "ltlformula" and
1170 //progressing the pointer forword
1171 for( i=0; i<10; i++ )
1172 keyWordLtlFormula[i] = pLine[i];
1173 quoteBegin = i;
1174 keyWordLtlFormula[10] = '\0';
1175 assert( strcmp( "ltlformula", keyWordLtlFormula ) == 0 );
1176 while( pLine[i] != '"' )
1177 i++;
1178 quoteBegin = i;
1179 i = strlen( pLine );
1180 while( pLine[i] != '"' )
1181 i--;
1182 quoteEnd = i;
1183 actualLtlFormula = (char *)malloc( sizeof(char) * (quoteEnd - quoteBegin) );
1184 //printf("\nThe input ltl formula = ");
1185 for( i = quoteBegin + 1, j = 0; i<quoteEnd; i++, j++ )
1186 //printf("%c", pLine[i] );
1187 actualLtlFormula[j] = pLine[i];
1188 actualLtlFormula[j] = '\0';
1189 Vec_PtrPush( vGlobalLtlArray, actualLtlFormula );
1190 return 1;
1191 }
1192
1193
1194 /**Function*************************************************************
1195
1196 Synopsis [Parses the latches line.]
1197
1198 Description []
1199
1200 SideEffects []
1201
1202 SeeAlso []
1203
1204 ***********************************************************************/
Io_MvParseLineLatch(Io_MvMod_t * p,char * pLine)1205 static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
1206 {
1207 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1208 Abc_Obj_t * pObj, * pNet;
1209 char * pToken;
1210 int Init;
1211 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1212 pToken = (char *)Vec_PtrEntry(vTokens,0);
1213 assert( !strcmp(pToken, "latch") );
1214 if ( Vec_PtrSize(vTokens) < 3 )
1215 {
1216 sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) );
1217 return 0;
1218 }
1219 // create latch
1220 if ( p->pResetLatch == NULL )
1221 {
1222 pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), (char *)Vec_PtrEntry(vTokens,2) );
1223 // get initial value
1224 if ( p->pMan->fBlifMv )
1225 Abc_LatchSetInit0( pObj );
1226 else
1227 {
1228 if ( Vec_PtrSize(vTokens) > 6 )
1229 printf( "Warning: Line %d has .latch directive with unrecognized entries (the total of %d entries).\n",
1230 Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
1231 if ( Vec_PtrSize(vTokens) > 3 )
1232 Init = atoi( (char *)Vec_PtrEntryLast(vTokens) );
1233 else
1234 Init = 2;
1235 if ( Init < 0 || Init > 3 )
1236 {
1237 sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
1238 return 0;
1239 }
1240 if ( Init == 0 )
1241 Abc_LatchSetInit0( pObj );
1242 else if ( Init == 1 )
1243 Abc_LatchSetInit1( pObj );
1244 else // if ( Init == 2 )
1245 Abc_LatchSetInitDc( pObj );
1246 }
1247 }
1248 else
1249 {
1250 // get the net corresponding to the output of the latch
1251 pNet = Abc_NtkFindOrCreateNet( p->pNtk, (char *)Vec_PtrEntry(vTokens,2) );
1252 // get the net corresponding to the latch output (feeding into reset MUX)
1253 pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
1254 // create latch
1255 pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
1256 // Abc_LatchSetInit0( pObj );
1257 Abc_LatchSetInit0( pObj );
1258 }
1259 return 1;
1260 }
1261
1262 /**Function*************************************************************
1263
1264 Synopsis [Parses the latches line.]
1265
1266 Description []
1267
1268 SideEffects []
1269
1270 SeeAlso []
1271
1272 ***********************************************************************/
Io_MvParseLineFlop(Io_MvMod_t * p,char * pLine)1273 static int Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine )
1274 {
1275 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1276 Abc_Obj_t * pObj;
1277 char * pToken, * pOutput, * pInput;
1278 int i, Init = 2;
1279 assert( !p->pMan->fBlifMv );
1280 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1281 pToken = (char *)Vec_PtrEntry(vTokens,0);
1282 assert( !strcmp(pToken, "flop") );
1283 // get flop output
1284 Vec_PtrForEachEntry( char *, vTokens, pToken, i )
1285 if ( pToken[0] == 'Q' && pToken[1] == '=' )
1286 break;
1287 if ( i == Vec_PtrSize(vTokens) )
1288 {
1289 sprintf( p->pMan->sError, "Line %d: Cannot find flop output.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
1290 return 0;
1291 }
1292 pOutput = pToken+2;
1293 // get flop input
1294 Vec_PtrForEachEntry( char *, vTokens, pToken, i )
1295 if ( pToken[0] == 'D' && pToken[1] == '=' )
1296 break;
1297 if ( i == Vec_PtrSize(vTokens) )
1298 {
1299 sprintf( p->pMan->sError, "Line %d: Cannot find flop input.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
1300 return 0;
1301 }
1302 pInput = pToken+2;
1303 // create latch
1304 pObj = Io_ReadCreateLatch( p->pNtk, pInput, pOutput );
1305 // get the init value
1306 Vec_PtrForEachEntry( char *, vTokens, pToken, i )
1307 {
1308 if ( !strncmp( pToken, "init=", 5 ) )
1309 {
1310 Init = 0;
1311 if ( pToken[5] == '1' )
1312 Init = 1;
1313 else if ( pToken[5] == '2' )
1314 Init = 2;
1315 else if ( pToken[5] != '0' )
1316 {
1317 sprintf( p->pMan->sError, "Line %d: Cannot read flop init value %s.", Io_MvGetLine(p->pMan, pToken), pToken );
1318 return 0;
1319 }
1320 break;
1321 }
1322 }
1323 if ( Init < 0 || Init > 2 )
1324 {
1325 sprintf( p->pMan->sError, "Line %d: Initial state of the flop is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
1326 return 0;
1327 }
1328 if ( Init == 0 )
1329 Abc_LatchSetInit0( pObj );
1330 else if ( Init == 1 )
1331 Abc_LatchSetInit1( pObj );
1332 else // if ( Init == 2 )
1333 Abc_LatchSetInitDc( pObj );
1334 return 1;
1335 }
1336
1337 /**Function*************************************************************
1338
1339 Synopsis [Parses the subckt line.]
1340
1341 Description []
1342
1343 SideEffects []
1344
1345 SeeAlso []
1346
1347 ***********************************************************************/
Io_MvParseLineSubckt(Io_MvMod_t * p,char * pLine)1348 static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine )
1349 {
1350 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1351 Abc_Ntk_t * pModel;
1352 Abc_Obj_t * pBox, * pNet, * pTerm;
1353 char * pToken, * pName, * pName2, ** ppNames;
1354 int nEquals, Last, i, k;
1355
1356 // split the line into tokens
1357 nEquals = Io_MvCountChars( pLine, '=' );
1358 Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
1359 pToken = (char *)Vec_PtrEntry(vTokens,0);
1360 assert( !strcmp(pToken, "subckt") );
1361 //printf( "%d ", nEquals );
1362
1363 // get the model for this box
1364 pName = (char *)Vec_PtrEntry(vTokens,1);
1365 // skip instance name for now
1366 for ( pToken = pName; *pToken; pToken++ )
1367 if ( *pToken == '|' )
1368 {
1369 *pToken = 0;
1370 break;
1371 }
1372 // find the model
1373 pModel = Abc_DesFindModelByName( p->pMan->pDesign, pName );
1374 if ( pModel == NULL )
1375 {
1376 sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName );
1377 return 0;
1378 }
1379 /*
1380 // check if the number of tokens is correct
1381 if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) )
1382 {
1383 sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).",
1384 Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) );
1385 return 0;
1386 }
1387 */
1388 // get the names
1389 ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv;
1390
1391 // create the box with these terminals
1392 if ( Abc_NtkHasBlackbox(pModel) )
1393 pBox = Abc_NtkCreateBlackbox( p->pNtk );
1394 else
1395 pBox = Abc_NtkCreateWhitebox( p->pNtk );
1396 pBox->pData = pModel;
1397 if ( p->pMan->fBlifMv )
1398 Abc_ObjAssignName( pBox, (char *)Vec_PtrEntry(vTokens,2), NULL );
1399 // go through formal inputs
1400 Last = 0;
1401 Abc_NtkForEachPi( pModel, pTerm, i )
1402 {
1403 // find this terminal among the actual inputs of the subcircuit
1404 pName2 = NULL;
1405 pName = Abc_ObjName(Abc_ObjFanout0(pTerm));
1406 for ( k = 0; k < nEquals; k++ )
1407 if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) )
1408 {
1409 pName2 = ppNames[2*((k+Last)%nEquals)+1];
1410 Last = k+Last+1;
1411 break;
1412 }
1413 /*
1414 if ( k == nEquals )
1415 {
1416 sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.",
1417 Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
1418 return 0;
1419 }
1420 */
1421 if ( pName2 == NULL )
1422 {
1423 Abc_Obj_t * pNode = Abc_NtkCreateNodeConst0( p->pNtk );
1424 //pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, " 0\n" );
1425 pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNode, "abc") );
1426 Abc_ObjAddFanin( pNet, pNode );
1427 pTerm = Abc_NtkCreateBi( p->pNtk );
1428 Abc_ObjAddFanin( pBox, pTerm );
1429 Abc_ObjAddFanin( pTerm, pNet );
1430 continue;
1431 }
1432 assert( pName2 != NULL );
1433
1434 // create the BI with the actual name
1435 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 );
1436 pTerm = Abc_NtkCreateBi( p->pNtk );
1437 Abc_ObjAddFanin( pBox, pTerm );
1438 Abc_ObjAddFanin( pTerm, pNet );
1439 }
1440 // go through formal outputs
1441 Last = 0;
1442 Abc_NtkForEachPo( pModel, pTerm, i )
1443 {
1444 // find this terminal among the actual outputs of the subcircuit
1445 pName2 = NULL;
1446 pName = Abc_ObjName(Abc_ObjFanin0(pTerm));
1447 for ( k = 0; k < nEquals; k++ )
1448 if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) )
1449 {
1450 pName2 = ppNames[2*((k+Last)%nEquals)+1];
1451 Last = k+Last+1;
1452 break;
1453 }
1454 /*
1455 if ( k == nEquals )
1456 {
1457 sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.",
1458 Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
1459 return 0;
1460 }
1461 */
1462
1463 // create the BI with the actual name
1464 pTerm = Abc_NtkCreateBo( p->pNtk );
1465 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 == NULL ? Abc_ObjNameSuffix(pTerm, "abc") : pName2 );
1466 Abc_ObjAddFanin( pNet, pTerm );
1467 Abc_ObjAddFanin( pTerm, pBox );
1468 }
1469 return 1;
1470 }
1471
1472 /**Function*************************************************************
1473
1474 Synopsis [Parses the subckt line.]
1475
1476 Description []
1477
1478 SideEffects []
1479
1480 SeeAlso []
1481
1482 ***********************************************************************/
Io_MvParseLineOnehot(Io_MvMod_t * p,char * pLine)1483 static Vec_Int_t * Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine )
1484 {
1485 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1486 // Vec_Ptr_t * vResult;
1487 Vec_Int_t * vResult;
1488 Abc_Obj_t * pNet, * pTerm;
1489 char * pToken;
1490 int nEquals, i;
1491
1492 // split the line into tokens
1493 nEquals = Io_MvCountChars( pLine, '=' );
1494 Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
1495 pToken = (char *)Vec_PtrEntry(vTokens,0);
1496 assert( !strcmp(pToken, "onehot") );
1497
1498 // iterate through the register names
1499 // vResult = Vec_PtrAlloc( Vec_PtrSize(vTokens) );
1500 vResult = Vec_IntAlloc( Vec_PtrSize(vTokens) );
1501 Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
1502 {
1503 // check if this register exists
1504 pNet = Abc_NtkFindNet( p->pNtk, pToken );
1505 if ( pNet == NULL )
1506 {
1507 sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" does not exist in the model \"%s\".",
1508 Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) );
1509 return NULL;
1510 }
1511 // check if this is register output net
1512 pTerm = Abc_ObjFanin0( pNet );
1513 if ( pTerm == NULL || Abc_ObjFanin0(pTerm) == NULL || !Abc_ObjIsLatch(Abc_ObjFanin0(pTerm)) )
1514 {
1515 sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" is not a register in the model \"%s\".",
1516 Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) );
1517 return NULL;
1518 }
1519 // save register name
1520 // Vec_PtrPush( vResult, Abc_ObjName(pNet) );
1521 Vec_IntPush( vResult, (int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pNext );
1522 // printf( "%d(%d) ", (int)Abc_ObjFanin0(pTerm)->pNext, ((int)Abc_ObjFanin0(pTerm)->pData) -1 );
1523 printf( "%d", ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pData)-1 );
1524 }
1525 printf( "\n" );
1526 return vResult;
1527 }
1528
1529
1530 /**Function*************************************************************
1531
1532 Synopsis [Parses the mv line.]
1533
1534 Description []
1535
1536 SideEffects []
1537
1538 SeeAlso []
1539
1540 ***********************************************************************/
Io_MvParseLineMv(Io_MvMod_t * p,char * pLine)1541 static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine )
1542 {
1543 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1544 Abc_Obj_t * pObj;
1545 Io_MvVar_t * pVar = NULL;
1546 Mem_Flex_t * pFlex;
1547 char * pName;
1548 int nCommas, nValues, i, k;
1549 // count commas and get the tokens
1550 nCommas = Io_MvCountChars( pLine, ',' );
1551 Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' );
1552 pName = (char *)Vec_PtrEntry(vTokens,0);
1553 assert( !strcmp(pName, "mv") );
1554 // get the number of values
1555 if ( Vec_PtrSize(vTokens) <= nCommas + 2 )
1556 {
1557 sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName) );
1558 return 0;
1559 }
1560 nValues = atoi( (char *)Vec_PtrEntry(vTokens,nCommas+2) );
1561 if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES )
1562 {
1563 sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).",
1564 Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES );
1565 return 0;
1566 }
1567 // if there is no symbolic values, quit
1568 if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 )
1569 return 1;
1570 if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues )
1571 {
1572 sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).",
1573 Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues );
1574 return 0;
1575 }
1576 // go through variables
1577 pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( p->pNtk );
1578 for ( i = 0; i <= nCommas; i++ )
1579 {
1580 pName = (char *)Vec_PtrEntry( vTokens, i+1 );
1581 pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName );
1582 // allocate variable
1583 pVar = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
1584 pVar->nValues = nValues;
1585 pVar->pNames = NULL;
1586 // create names
1587 if ( Vec_PtrSize(vTokens) > nCommas + 3 )
1588 {
1589 pVar->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * nValues );
1590 Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nCommas + 3 )
1591 {
1592 pVar->pNames[k-(nCommas + 3)] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pName) + 1 );
1593 strcpy( pVar->pNames[k-(nCommas + 3)], pName );
1594 }
1595 }
1596 // save the variable
1597 Abc_ObjSetMvVar( pObj, pVar );
1598 }
1599 // make sure the names are unique
1600 assert(pVar);
1601 if ( pVar->pNames )
1602 {
1603 for ( i = 0; i < nValues; i++ )
1604 for ( k = i+1; k < nValues; k++ )
1605 if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) )
1606 {
1607 pName = (char *)Vec_PtrEntry(vTokens,0);
1608 sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.",
1609 Io_MvGetLine(p->pMan, pName), pVar->pNames[i] );
1610 return 0;
1611 }
1612 }
1613 return 1;
1614 }
1615
1616 /**Function*************************************************************
1617
1618 Synopsis [Writes the values into the BLIF-MV representation for the node.]
1619
1620 Description []
1621
1622 SideEffects []
1623
1624 SeeAlso []
1625
1626 ***********************************************************************/
Io_MvWriteValues(Abc_Obj_t * pNode,Vec_Str_t * vFunc)1627 static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc )
1628 {
1629 char Buffer[10];
1630 Abc_Obj_t * pFanin;
1631 int i;
1632 // add the fanin number of values
1633 Abc_ObjForEachFanin( pNode, pFanin, i )
1634 {
1635 sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) );
1636 Vec_StrPrintStr( vFunc, Buffer );
1637 Vec_StrPush( vFunc, ' ' );
1638 }
1639 // add the node number of values
1640 sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) );
1641 Vec_StrPrintStr( vFunc, Buffer );
1642 Vec_StrPush( vFunc, '\n' );
1643 return 1;
1644 }
1645
1646 /**Function*************************************************************
1647
1648 Synopsis [Translated one literal.]
1649
1650 Description []
1651
1652 SideEffects []
1653
1654 SeeAlso []
1655
1656 ***********************************************************************/
Io_MvParseLiteralMv(Io_MvMod_t * p,Abc_Obj_t * pNode,char * pToken,Vec_Str_t * vFunc,int iLit)1657 static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit )
1658 {
1659 char Buffer[10];
1660 Io_MvVar_t * pVar;
1661 Abc_Obj_t * pFanin, * pNet;
1662 char * pCur, * pNext;
1663 int i;
1664 // consider the equality literal
1665 if ( pToken[0] == '=' )
1666 {
1667 // find the fanins
1668 Abc_ObjForEachFanin( pNode, pFanin, i )
1669 if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) )
1670 break;
1671 if ( i == Abc_ObjFaninNum(pNode) )
1672 {
1673 sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.",
1674 Io_MvGetLine(p->pMan, pToken), pToken + 1 );
1675 return 0;
1676 }
1677 Vec_StrPush( vFunc, '=' );
1678 sprintf( Buffer, "%d", i );
1679 Vec_StrPrintStr( vFunc, Buffer );
1680 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
1681 return 1;
1682 }
1683 // consider regular literal
1684 assert( iLit < Abc_ObjFaninNum(pNode) );
1685 pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode);
1686 pVar = (Io_MvVar_t *)Abc_ObjMvVar( pNet );
1687 // if the var is absent or has no symbolic values quit
1688 if ( pVar == NULL || pVar->pNames == NULL )
1689 {
1690 Vec_StrPrintStr( vFunc, pToken );
1691 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
1692 return 1;
1693 }
1694 // parse the literal using symbolic values
1695 for ( pCur = pToken; *pCur; pCur++ )
1696 {
1697 if ( Io_MvCharIsMvSymb(*pCur) )
1698 {
1699 Vec_StrPush( vFunc, *pCur );
1700 continue;
1701 }
1702 // find the next MvSymb char
1703 for ( pNext = pCur+1; *pNext; pNext++ )
1704 if ( Io_MvCharIsMvSymb(*pNext) )
1705 break;
1706 // look for the value name
1707 for ( i = 0; i < pVar->nValues; i++ )
1708 if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) )
1709 break;
1710 if ( i == pVar->nValues )
1711 {
1712 *pNext = 0;
1713 sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".",
1714 Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) );
1715 return 0;
1716 }
1717 // value name is found
1718 sprintf( Buffer, "%d", i );
1719 Vec_StrPrintStr( vFunc, Buffer );
1720 // update the pointer
1721 pCur = pNext - 1;
1722 }
1723 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
1724 return 1;
1725 }
1726
1727 /**Function*************************************************************
1728
1729 Synopsis [Constructs the MV-SOP cover from the file parsing info.]
1730
1731 Description []
1732
1733 SideEffects []
1734
1735 SeeAlso []
1736
1737 ***********************************************************************/
Io_MvParseTableMv(Io_MvMod_t * p,Abc_Obj_t * pNode,Vec_Ptr_t * vTokens2,int nInputs,int nOutputs,int iOut)1738 static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut )
1739 {
1740 Vec_Str_t * vFunc = p->pMan->vFunc;
1741 char * pFirst, * pToken;
1742 int iStart, i;
1743 // prepare the place for the cover
1744 Vec_StrClear( vFunc );
1745 // write the number of values
1746 // Io_MvWriteValues( pNode, vFunc );
1747 // get the first token
1748 pFirst = (char *)Vec_PtrEntry( vTokens2, 0 );
1749 if ( pFirst[0] == '.' )
1750 {
1751 // write the default literal
1752 Vec_StrPush( vFunc, 'd' );
1753 pToken = (char *)Vec_PtrEntry(vTokens2, 1 + iOut);
1754 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
1755 return NULL;
1756 iStart = 1 + nOutputs;
1757 }
1758 else
1759 iStart = 0;
1760 // write the remaining literals
1761 while ( iStart < Vec_PtrSize(vTokens2) )
1762 {
1763 // input literals
1764 for ( i = 0; i < nInputs; i++ )
1765 {
1766 pToken = (char *)Vec_PtrEntry( vTokens2, iStart + i );
1767 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) )
1768 return NULL;
1769 }
1770 // output literal
1771 pToken = (char *)Vec_PtrEntry( vTokens2, iStart + nInputs + iOut );
1772 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
1773 return NULL;
1774 // update the counter
1775 iStart += nInputs + nOutputs;
1776 }
1777 Vec_StrPush( vFunc, '\0' );
1778 return Vec_StrArray( vFunc );
1779 }
1780
1781 /**Function*************************************************************
1782
1783 Synopsis [Adds reset circuitry corresponding to latch with pName.]
1784
1785 Description [Returns the reset node's net.]
1786
1787 SideEffects []
1788
1789 SeeAlso []
1790
1791 ***********************************************************************/
Io_MvParseAddResetCircuit(Io_MvMod_t * p,char * pName)1792 static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
1793 {
1794 char Buffer[50];
1795 Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
1796 Io_MvVar_t * pVar;
1797 // make sure the reset latch exists
1798 assert( p->pResetLatch != NULL );
1799 // get the reset net
1800 pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
1801 // get the output net
1802 pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
1803 // get the data nets
1804 pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
1805 pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
1806 // duplicate MV variables
1807 if ( Abc_NtkMvVar(p->pNtk) )
1808 {
1809 pVar = (Io_MvVar_t *)Abc_ObjMvVar( pOutNet );
1810 Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
1811 Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
1812 }
1813 // create the node
1814 pNode = Abc_NtkCreateNode( p->pNtk );
1815 // create the output net
1816 Abc_ObjAddFanin( pOutNet, pNode );
1817 // create the function
1818 if ( p->pMan->fBlifMv )
1819 {
1820 // Vec_Att_t * p = Abc_NtkMvVar( pNtk );
1821 // int nValues = Abc_ObjMvVarNum(pOutNet);
1822 // sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
1823 sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
1824 pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, Buffer );
1825 }
1826 else
1827 pNode->pData = Abc_SopCreateMux( (Mem_Flex_t *)p->pNtk->pManFunc );
1828 // add nets
1829 Abc_ObjAddFanin( pNode, pResetLONet );
1830 Abc_ObjAddFanin( pNode, pData1Net );
1831 Abc_ObjAddFanin( pNode, pData0Net );
1832 return pData0Net;
1833 }
1834
1835 /**Function*************************************************************
1836
1837 Synopsis [Parses the nodes line.]
1838
1839 Description []
1840
1841 SideEffects []
1842
1843 SeeAlso []
1844
1845 ***********************************************************************/
Io_MvParseLineNamesMvOne(Io_MvMod_t * p,Vec_Ptr_t * vTokens,Vec_Ptr_t * vTokens2,int nInputs,int nOutputs,int iOut,int fReset)1846 static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset )
1847 {
1848 Abc_Obj_t * pNet, * pNode;
1849 char * pName;
1850 // get the output name
1851 pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut );
1852 // create the node
1853 if ( fReset )
1854 {
1855 pNet = Abc_NtkFindNet( p->pNtk, pName );
1856 if ( pNet == NULL )
1857 {
1858 sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
1859 return 0;
1860 }
1861 /*
1862 if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) )
1863 {
1864 sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName );
1865 return 0;
1866 }
1867 */
1868 // construct the reset circuit and get the reset net feeding into it
1869 pNet = Io_MvParseAddResetCircuit( p, pName );
1870 // create fanins
1871 pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
1872 assert( nInputs == Vec_PtrSize(vTokens) - 2 );
1873 }
1874 else
1875 {
1876 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
1877 if ( Abc_ObjFaninNum(pNet) > 0 )
1878 {
1879 sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
1880 return 0;
1881 }
1882 pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs );
1883 }
1884 // create the cover
1885 pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut );
1886 if ( pNode->pData == NULL )
1887 return 0;
1888 pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData );
1889 //printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData );
1890 return 1;
1891 }
1892
1893 /**Function*************************************************************
1894
1895 Synopsis [Parses the nodes line.]
1896
1897 Description []
1898
1899 SideEffects []
1900
1901 SeeAlso []
1902
1903 ***********************************************************************/
Io_MvParseLineNamesMv(Io_MvMod_t * p,char * pLine,int fReset)1904 static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
1905 {
1906 Vec_Ptr_t * vTokens = p->pMan->vTokens;
1907 Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
1908 Abc_Obj_t * pNet;
1909 char * pName, * pFirst, * pArrow;
1910 int nInputs, nOutputs, nLiterals, nLines, i;
1911 assert( p->pMan->fBlifMv );
1912 // get the arrow if it is present
1913 pArrow = Io_MvFindArrow( pLine );
1914 if ( !p->pMan->fBlifMv && pArrow )
1915 {
1916 sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) );
1917 return 0;
1918 }
1919 // split names line into tokens
1920 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
1921 if ( fReset )
1922 assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "r") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "reset") );
1923 else
1924 assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "table") );
1925 // find the number of inputs and outputs
1926 nInputs = Vec_PtrSize(vTokens) - 2;
1927 nOutputs = 1;
1928 if ( pArrow != NULL )
1929 {
1930 for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- )
1931 if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) )
1932 {
1933 nInputs--;
1934 nOutputs++;
1935 }
1936 }
1937 // split table into tokens
1938 pName = (char *)Vec_PtrEntryLast( vTokens );
1939 Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) );
1940 pFirst = (char *)Vec_PtrEntry( vTokens2, 0 );
1941 if ( pFirst[0] == '.' )
1942 {
1943 assert( pFirst[1] == 'd' );
1944 nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs;
1945 }
1946 else
1947 nLiterals = Vec_PtrSize(vTokens2);
1948 // check the number of lines
1949 if ( nLiterals % (nInputs + nOutputs) != 0 )
1950 {
1951 sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName );
1952 return 0;
1953 }
1954 // check for the ND table
1955 nLines = nLiterals / (nInputs + nOutputs);
1956 if ( nInputs == 0 && nLines > 1 )
1957 {
1958 // add the outputs to the PIs
1959 for ( i = 0; i < nOutputs; i++ )
1960 {
1961 pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
1962 // get the net corresponding to this node
1963 pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
1964 if ( fReset )
1965 {
1966 assert( p->pResetLatch != NULL );
1967 // construct the reset circuit and get the reset net feeding into it
1968 pNet = Io_MvParseAddResetCircuit( p, pName );
1969 }
1970 // add the new PI node
1971 // Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
1972 // fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
1973 p->pMan->nNDnodes++;
1974 Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
1975 }
1976 return 1;
1977 }
1978 // iterate through the outputs
1979 for ( i = 0; i < nOutputs; i++ )
1980 {
1981 if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) )
1982 return 0;
1983 }
1984 return 1;
1985 }
1986
1987
1988 /**Function*************************************************************
1989
1990 Synopsis [Constructs the SOP cover from the file parsing info.]
1991
1992 Description []
1993
1994 SideEffects []
1995
1996 SeeAlso []
1997
1998 ***********************************************************************/
Io_MvParseTableBlif(Io_MvMod_t * p,char * pTable,int nFanins)1999 static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
2000 {
2001 Vec_Ptr_t * vTokens = p->pMan->vTokens;
2002 Vec_Str_t * vFunc = p->pMan->vFunc;
2003 char * pProduct, * pOutput, c;
2004 int i, Polarity = -1;
2005
2006 p->pMan->nTablesRead++;
2007 // get the tokens
2008 Io_MvSplitIntoTokens( vTokens, pTable, '.' );
2009 if ( Vec_PtrSize(vTokens) == 0 )
2010 return Abc_SopCreateConst0( (Mem_Flex_t *)p->pNtk->pManFunc );
2011 if ( Vec_PtrSize(vTokens) == 1 )
2012 {
2013 pOutput = (char *)Vec_PtrEntry( vTokens, 0 );
2014 c = pOutput[0];
2015 if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] )
2016 {
2017 sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput );
2018 return NULL;
2019 }
2020 return pOutput[0] == '0' ? Abc_SopCreateConst0((Mem_Flex_t *)p->pNtk->pManFunc) : Abc_SopCreateConst1((Mem_Flex_t *)p->pNtk->pManFunc);
2021 }
2022 pProduct = (char *)Vec_PtrEntry( vTokens, 0 );
2023 if ( Vec_PtrSize(vTokens) % 2 == 1 )
2024 {
2025 sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
2026 return NULL;
2027 }
2028 // parse the table
2029 Vec_StrClear( vFunc );
2030 for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
2031 {
2032 pProduct = (char *)Vec_PtrEntry( vTokens, 2*i + 0 );
2033 pOutput = (char *)Vec_PtrEntry( vTokens, 2*i + 1 );
2034 if ( strlen(pProduct) != (unsigned)nFanins )
2035 {
2036 sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins );
2037 return NULL;
2038 }
2039 c = pOutput[0];
2040 if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] )
2041 {
2042 sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput );
2043 return NULL;
2044 }
2045 if ( Polarity == -1 )
2046 Polarity = (c=='1' || c=='x');
2047 else if ( Polarity != (c=='1' || c=='x') )
2048 {
2049 sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
2050 return NULL;
2051 }
2052 // parse one product
2053 Vec_StrPrintStr( vFunc, pProduct );
2054 Vec_StrPush( vFunc, ' ' );
2055 Vec_StrPush( vFunc, pOutput[0] );
2056 Vec_StrPush( vFunc, '\n' );
2057 }
2058 Vec_StrPush( vFunc, '\0' );
2059 return Vec_StrArray( vFunc );
2060 }
2061
2062 /**Function*************************************************************
2063
2064 Synopsis [Parses the nodes line.]
2065
2066 Description []
2067
2068 SideEffects []
2069
2070 SeeAlso []
2071
2072 ***********************************************************************/
Io_MvParseLineNamesBlif(Io_MvMod_t * p,char * pLine)2073 static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
2074 {
2075 Vec_Ptr_t * vTokens = p->pMan->vTokens;
2076 Abc_Obj_t * pNet, * pNode;
2077 char * pName;
2078 assert( !p->pMan->fBlifMv );
2079 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
2080 // parse the mapped node
2081 if ( !strcmp((char *)Vec_PtrEntry(vTokens,0), "gate") )
2082 return Io_MvParseLineGateBlif( p, vTokens );
2083 // parse the regular name line
2084 assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") );
2085 pName = (char *)Vec_PtrEntryLast( vTokens );
2086 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
2087 if ( Abc_ObjFaninNum(pNet) > 0 )
2088 {
2089 sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
2090 return 0;
2091 }
2092 // create fanins
2093 pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 );
2094 // parse the table of this node
2095 pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) );
2096 if ( pNode->pData == NULL )
2097 return 0;
2098 pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData );
2099 return 1;
2100 }
2101
2102 ABC_NAMESPACE_IMPL_END
2103
2104 #include "map/mio/mio.h"
2105 #include "base/main/main.h"
2106
2107 ABC_NAMESPACE_IMPL_START
2108
2109
2110 /**Function*************************************************************
2111
2112 Synopsis [Parses the nodes line.]
2113
2114 Description []
2115
2116 SideEffects []
2117
2118 SeeAlso []
2119
2120 ***********************************************************************/
Io_MvParseLineShortBlif(Io_MvMod_t * p,char * pLine)2121 static int Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine )
2122 {
2123 Vec_Ptr_t * vTokens = p->pMan->vTokens;
2124 Abc_Obj_t * pNet, * pNode;
2125 char * pName;
2126 assert( !p->pMan->fBlifMv );
2127 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
2128 if ( Vec_PtrSize(vTokens) != 3 )
2129 {
2130 sprintf( p->pMan->sError, "Line %d: Expecting three entries in the .short line.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
2131 return 0;
2132 }
2133 // parse the regular name line
2134 assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "short") );
2135 pName = (char *)Vec_PtrEntryLast( vTokens );
2136 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
2137 if ( Abc_ObjFaninNum(pNet) > 0 )
2138 {
2139 sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
2140 return 0;
2141 }
2142 // create fanins
2143 pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), 1 );
2144 // parse the table of this node
2145 if ( p->pNtk->ntkFunc == ABC_FUNC_MAP )
2146 {
2147 Mio_Library_t * pGenlib;
2148 Mio_Gate_t * pGate;
2149 // check that the library is available
2150 pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
2151 if ( pGenlib == NULL )
2152 {
2153 sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
2154 return 0;
2155 }
2156 // get the gate
2157 pGate = Mio_LibraryReadBuf( pGenlib );
2158 if ( pGate == NULL )
2159 {
2160 sprintf( p->pMan->sError, "Line %d: Cannot find buffer gate in the library.", Io_MvGetLine(p->pMan, pName) );
2161 return 0;
2162 }
2163 Abc_ObjSetData( pNode, pGate );
2164 }
2165 else
2166 pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, "1 1\n" );
2167 return 1;
2168 }
2169
2170 /**Function*************************************************************
2171
2172 Synopsis [Duplicate the MV variable.]
2173
2174 Description []
2175
2176 SideEffects []
2177
2178 SeeAlso []
2179
2180 ***********************************************************************/
Abc_NtkMvVarDup(Abc_Ntk_t * pNtk,Io_MvVar_t * pVar)2181 Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
2182 {
2183 Mem_Flex_t * pFlex;
2184 Io_MvVar_t * pVarDup;
2185 int i;
2186 if ( pVar == NULL )
2187 return NULL;
2188 pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pNtk );
2189 assert( pFlex != NULL );
2190 pVarDup = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
2191 pVarDup->nValues = pVar->nValues;
2192 pVarDup->pNames = NULL;
2193 if ( pVar->pNames == NULL )
2194 return pVarDup;
2195 pVarDup->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
2196 for ( i = 0; i < pVar->nValues; i++ )
2197 {
2198 pVarDup->pNames[i] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
2199 strcpy( pVarDup->pNames[i], pVar->pNames[i] );
2200 }
2201 return pVarDup;
2202 }
2203
2204 /**Function*************************************************************
2205
2206 Synopsis []
2207
2208 Description []
2209
2210 SideEffects []
2211
2212 SeeAlso []
2213
2214 ***********************************************************************/
Io_ReadBlifCleanName(char * pName)2215 static char * Io_ReadBlifCleanName( char * pName )
2216 {
2217 int i, Length;
2218 Length = strlen(pName);
2219 for ( i = 0; i < Length; i++ )
2220 if ( pName[i] == '=' )
2221 return pName + i + 1;
2222 return NULL;
2223 }
2224
2225 /**Function*************************************************************
2226
2227 Synopsis []
2228
2229 Description []
2230
2231 SideEffects []
2232
2233 SeeAlso []
2234
2235 ***********************************************************************/
Io_MvParseLineGateBlif(Io_MvMod_t * p,Vec_Ptr_t * vTokens)2236 static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens )
2237 {
2238 extern int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin );
2239 Mio_Library_t * pGenlib;
2240 Mio_Gate_t * pGate;
2241 Abc_Obj_t * pNode;
2242 char ** ppNames, * pName;
2243 int i, nNames;
2244
2245 pName = (char *)vTokens->pArray[0];
2246
2247 // check that the library is available
2248 pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
2249 if ( pGenlib == NULL )
2250 {
2251 sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
2252 return 0;
2253 }
2254
2255 // create a new node and add it to the network
2256 if ( vTokens->nSize < 2 )
2257 {
2258 sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) );
2259 return 0;
2260 }
2261
2262 // get the gate
2263 pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL );
2264 if ( pGate == NULL )
2265 {
2266 sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] );
2267 return 0;
2268 }
2269
2270 // if this is the first line with gate, update the network type
2271 if ( Abc_NtkNodeNum(p->pNtk) == 0 && p->pNtk->ntkFunc == ABC_FUNC_SOP )
2272 {
2273 assert( p->pNtk->ntkFunc == ABC_FUNC_SOP );
2274 p->pNtk->ntkFunc = ABC_FUNC_MAP;
2275 Mem_FlexStop( (Mem_Flex_t *)p->pNtk->pManFunc, 0 );
2276 p->pNtk->pManFunc = pGenlib;
2277 if ( p->pMan && p->pMan->pDesign && Vec_PtrSize(p->pMan->pDesign->vModules) > 0 )
2278 {
2279 Abc_Ntk_t * pModel; int k;
2280 Vec_PtrForEachEntry( Abc_Ntk_t *, p->pMan->pDesign->vModules, pModel, k )
2281 {
2282 if ( pModel == p->pNtk )
2283 continue;
2284 assert( pModel->ntkFunc == ABC_FUNC_SOP );
2285 pModel->ntkFunc = ABC_FUNC_MAP;
2286 Mem_FlexStop( (Mem_Flex_t *)pModel->pManFunc, 0 );
2287 pModel->pManFunc = pGenlib;
2288 }
2289 }
2290 }
2291
2292 // reorder the formal inputs to be in the same order as in the gate
2293 if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) )
2294 {
2295 sprintf( p->pMan->sError, "Line %d: Mismatch in the fanins of gate \"%s\".", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] );
2296 return 0;
2297 }
2298
2299 // remove the formal parameter names
2300 for ( i = 2; i < vTokens->nSize; i++ )
2301 {
2302 if ( vTokens->pArray[i] == NULL )
2303 continue;
2304 vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] );
2305 if ( vTokens->pArray[i] == NULL )
2306 {
2307 sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) );
2308 return 0;
2309 }
2310 }
2311
2312 // create the node
2313 if ( Mio_GateReadTwin(pGate) == NULL )
2314 {
2315 nNames = vTokens->nSize - 3;
2316 ppNames = (char **)vTokens->pArray + 2;
2317 pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
2318 Abc_ObjSetData( pNode, pGate );
2319 }
2320 else
2321 {
2322 nNames = vTokens->nSize - 4;
2323 ppNames = (char **)vTokens->pArray + 2;
2324 assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL );
2325 if ( ppNames[nNames] )
2326 {
2327 pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
2328 Abc_ObjSetData( pNode, pGate );
2329 }
2330 if ( ppNames[nNames+1] )
2331 {
2332 pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames+1], ppNames, nNames );
2333 Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) );
2334 }
2335 }
2336
2337 return 1;
2338 }
2339
2340 /**Function*************************************************************
2341
2342 Synopsis [Box mapping procedures.]
2343
2344 Description []
2345
2346 SideEffects []
2347
2348 SeeAlso []
2349
2350 ***********************************************************************/
Abc_MapBoxSetPrevNext(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)2351 static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
2352 {
2353 Abc_Obj_t * pNode;
2354 pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
2355 Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id );
2356 pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
2357 Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id );
2358 }
Abc_MapBox2Next(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)2359 static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
2360 {
2361 Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
2362 return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
2363 }
Abc_MapBox2Prev(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)2364 static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
2365 {
2366 Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
2367 return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
2368 }
2369
2370 ////////////////////////////////////////////////////////////////////////
2371 /// END OF FILE ///
2372 ////////////////////////////////////////////////////////////////////////
2373
2374
2375 ABC_NAMESPACE_IMPL_END
2376
2377