cbaWriteVer.c 40.9 KB
Newer Older
1 2
/**CFile****************************************************************

3
  FileName    [cbaWriteVer.c]
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

7
  PackageName [Hierarchical word-level netlist.]
8

9
  Synopsis    [Verilog writer.]
10 11 12 13 14 15 16

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 29, 2014.]

17
  Revision    [$Id: cbaWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
18 19 20 21 22

***********************************************************************/

#include "cba.h"
#include "cbaPrs.h"
23
#include "map/mio/mio.h"
24
#include "base/main/main.h"
25 26 27 28 29 30 31 32 33 34 35 36

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  
  Synopsis    []  
  
  Description []  
                 
  SideEffects []  
  
  SeeAlso     []  
  
***********************************************************************/
void Cba_ManCreatePrimMap( char ** pMap )
{
    memset( pMap, 0, sizeof(char *) * CBA_BOX_LAST );

    pMap[ CBA_BOX_SLICE  ] = "sli";
52
    pMap[ CBA_BOX_CONCAT ] = "icc";
53 54 55 56 57 58 59 60 61 62 63 64

    pMap[ CBA_BOX_BUF    ] = "";
    pMap[ CBA_BOX_INV    ] = "~";
    pMap[ CBA_BOX_AND    ] = "&"; 
    pMap[ CBA_BOX_NAND   ] = "&"; 
    pMap[ CBA_BOX_OR     ] = "|"; 
    pMap[ CBA_BOX_NOR    ] = "|"; 
    pMap[ CBA_BOX_XOR    ] = "^"; 
    pMap[ CBA_BOX_XNOR   ] = "^"; 
    pMap[ CBA_BOX_SHARP  ] = "&"; 
    pMap[ CBA_BOX_SHARPL ] = "&"; 
    pMap[ CBA_BOX_MUX    ] = "?"; 
65
    pMap[ CBA_BOX_MAJ    ] = "maj"; 
66 67 68 69 70 71 72 73
    pMap[ CBA_BOX_RAND   ] = "&"; 
    pMap[ CBA_BOX_RNAND  ] = "~&"; 
    pMap[ CBA_BOX_ROR    ] = "|"; 
    pMap[ CBA_BOX_RNOR   ] = "~|"; 
    pMap[ CBA_BOX_RXOR   ] = "^"; 
    pMap[ CBA_BOX_RXNOR  ] = "~^"; 
    pMap[ CBA_BOX_LNOT   ] = "!"; 
    pMap[ CBA_BOX_LAND   ] = "&&"; 
74
    pMap[ CBA_BOX_LNAND  ] = "logic nand"; 
75
    pMap[ CBA_BOX_LOR    ] = "||"; 
76
    pMap[ CBA_BOX_LNOR   ] = "logic nor"; 
77
    pMap[ CBA_BOX_LXOR   ] = "^^"; 
78
    pMap[ CBA_BOX_LXNOR  ] = "logic xnor"; 
79 80
    pMap[ CBA_BOX_NMUX   ] = "nmux"; 
    pMap[ CBA_BOX_SEL    ] = "sel"; 
81 82 83
    pMap[ CBA_BOX_PSEL   ] = "prio-select"; 
    pMap[ CBA_BOX_ENC    ] = "enc"; 
    pMap[ CBA_BOX_PENC   ] = "prio-enc"; 
84
    pMap[ CBA_BOX_DEC    ] = "dec"; 
85
    pMap[ CBA_BOX_EDEC   ] = "enable-dec"; 
86 87 88 89 90 91 92 93 94
    pMap[ CBA_BOX_ADD    ] = "+"; 
    pMap[ CBA_BOX_SUB    ] = "-"; 
    pMap[ CBA_BOX_MUL    ] = "*"; 
    pMap[ CBA_BOX_DIV    ] = "/"; 
    pMap[ CBA_BOX_MOD    ] = "%"; 
    pMap[ CBA_BOX_REM    ] = "%"; 
    pMap[ CBA_BOX_POW    ] = "**"; 
    pMap[ CBA_BOX_MIN    ] = "-"; 
    pMap[ CBA_BOX_SQRT   ] = "@"; 
95
    pMap[ CBA_BOX_ABS    ] = "abs"; 
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
    pMap[ CBA_BOX_LTHAN  ] = "<"; 
    pMap[ CBA_BOX_LETHAN ] = "<="; 
    pMap[ CBA_BOX_METHAN ] = ">="; 
    pMap[ CBA_BOX_MTHAN  ] = ">"; 
    pMap[ CBA_BOX_EQU    ] = "=="; 
    pMap[ CBA_BOX_NEQU   ] = "!="; 
    pMap[ CBA_BOX_SHIL   ] = "<<"; 
    pMap[ CBA_BOX_SHIR   ] = ">>"; 
    pMap[ CBA_BOX_SHILA  ] = "<<<"; 
    pMap[ CBA_BOX_SHIRA  ] = ">>>"; 
    pMap[ CBA_BOX_ROTL   ] = "rotL"; 
    pMap[ CBA_BOX_ROTR   ] = "rotR"; 

    pMap[ CBA_BOX_TRI    ] = "tri";
    pMap[ CBA_BOX_RAM    ] = "ram";
    pMap[ CBA_BOX_RAMR   ] = "ramR";
    pMap[ CBA_BOX_RAMW   ] = "ramW";
    pMap[ CBA_BOX_RAMWC  ] = "ramWC";
    pMap[ CBA_BOX_RAMBOX ] = "ramBox";

    pMap[ CBA_BOX_LATCH  ] = "lat";
    pMap[ CBA_BOX_LATCHRS] = "latrs";
    pMap[ CBA_BOX_DFF    ] = "dff";
    pMap[ CBA_BOX_DFFRS  ] = "dffrs";
}

/**Function*************************************************************
123 124 125 126 127 128 129 130 131 132

  Synopsis    [Writing parser state into a file.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
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
static inline int Prs_NameIsLegalInVerilog( char * pName, int NameId )
{
    // identifier ::= simple_identifier | escaped_identifier
    // simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$]
    // escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space
    // white_space ::= space | tab | newline
    assert( pName != NULL && *pName != '\0' );
    if ( *pName == '\\' )
        return 1;
    if ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c
        return 0;
    if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' )
        return 0;
    while ( *(++pName) )
        if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' ) 
            return 0;
    return 1;
}
char * Prs_ObjGetName( Prs_Ntk_t * p, int NameId )
{
    char * pName = Prs_NtkStr(p, NameId);
    if ( pName == NULL )
        return pName;
    if ( Prs_NameIsLegalInVerilog(pName, NameId) )
        return pName;
    return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "\\%s ", pName );
}
160 161 162 163 164 165 166 167 168
static inline char * Prs_ManWriteRange( Prs_Ntk_t * p, int RangeId, int fSlice )
{
    int Left  = RangeId ? Hash_IntObjData0( p->vHash, RangeId ) : 0;
    int Right = RangeId ? Hash_IntObjData1( p->vHash, RangeId ) : 0;
    if ( Left == Right && fSlice )
        return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d]", Right );
    else
        return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d:%d]", Left, Right );
}
169
static void Prs_ManWriteVerilogConcat( FILE * pFile, Prs_Ntk_t * p, int Con )
170
{
171
    extern void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd );
172
    Vec_Int_t * vSigs = Prs_CatSignals(p, Con);
Alan Mishchenko committed
173
    fprintf( pFile, "{" );
174
    Prs_ManWriteVerilogArray( pFile, p, vSigs, 0 );
Alan Mishchenko committed
175
    fprintf( pFile, "}" );
176
}
177
static void Prs_ManWriteVerilogSignal( FILE * pFile, Prs_Ntk_t * p, int Sig )
178
{
179
    int Value = Abc_Lit2Var2( Sig );
180
    Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig );
181
    if ( Type == CBA_PRS_NAME )
182
        fprintf( pFile, "%s", Prs_ObjGetName(p, Value) );
183 184
    else if ( Type == CBA_PRS_CONST )
        fprintf( pFile, "%s", Prs_NtkConst(p, Value) );
185
    else if ( Type == CBA_PRS_SLICE )
186
        fprintf( pFile, "%s%s", Prs_ObjGetName(p, Prs_SliceName(p, Value)), Prs_ManWriteRange(p, Prs_SliceRange(p, Value), 1) );
187 188 189 190
    else if ( Type == CBA_PRS_CONCAT )
        Prs_ManWriteVerilogConcat( pFile, p, Value );
    else assert( 0 );
}
191
void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd )
192
{
193
    int i, Sig, fFirst = 1;
194
    assert( Vec_IntSize(vSigs) > 0 );
195
    Vec_IntForEachEntry( vSigs, Sig, i )
Alan Mishchenko committed
196
    {
197 198
        if ( fOdd && !(i & 1) )
            continue;
199
        fprintf( pFile, "%s", fFirst ? "" : ", " );
200
        Prs_ManWriteVerilogSignal( pFile, p, Sig );
201
        fFirst = 0;
Alan Mishchenko committed
202
    }
203
}
204
static void Prs_ManWriteVerilogArray2( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs )
205
{
206 207 208
    int i, FormId, ActSig;
    assert( Vec_IntSize(vSigs) % 2 == 0 );
    Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
Alan Mishchenko committed
209
    {
210
        fprintf( pFile, "." );
211
        fprintf( pFile, "%s", Prs_ObjGetName(p, FormId) );
212 213 214
        fprintf( pFile, "(" );
        Prs_ManWriteVerilogSignal( pFile, p, ActSig );
        fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " );
Alan Mishchenko committed
215
    }
216
}
217
static void Prs_ManWriteVerilogMux( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs )
218
{
219 220 221 222
    int i, FormId, ActSig;
    char * pStrs[4] = { " = ", " ? ", " : ", ";\n" };
    assert( Vec_IntSize(vSigs) == 8 );
    fprintf( pFile, "  assign " );
223
    Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vSigs, 1) );
224
    fprintf( pFile, "%s", pStrs[0] );
225
    Vec_IntForEachEntryDoubleStart( vSigs, FormId, ActSig, i, 2 )
226 227
    {
        Prs_ManWriteVerilogSignal( pFile, p, ActSig );
228
        fprintf( pFile, "%s", pStrs[i/2] );
229
    }
230
}
231
static void Prs_ManWriteVerilogBoxes( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames )
232
{
233
    Vec_Int_t * vBox; int i, k;
234
    Prs_NtkForEachBox( p, vBox, i )
235
    {
236
        Cba_ObjType_t NtkId = (Cba_ObjType_t)Prs_BoxNtk(p, i);
237 238
        //char * pNtkName = Prs_ObjGetName(p, Prs_BoxName(p, i));
        if ( NtkId == CBA_BOX_MUX && Prs_BoxIsNode(p, i) )
239
            Prs_ManWriteVerilogMux( pFile, p, vBox );
240
        else if ( Prs_BoxIsNode(p, i) ) // node
241
        {
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
            fprintf( pFile, "  assign " );
            Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 1) );
            fprintf( pFile, " = " );
            if ( Cba_TypeIsUnary(NtkId) )
            {
                fprintf( pFile, "%s", pTypeNames[NtkId] );
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
            }
            else if ( NtkId == CBA_BOX_NMUX )
            {
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
                fprintf( pFile, " ? " );
                for ( k = 5; k < Vec_IntSize(vBox); k += 2 )
                {
                    if ( k > 5 ) fprintf( pFile, " : " );
                    Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, k) );
                }
            }
            else if ( NtkId == CBA_BOX_ADD )
            {
                if ( Vec_IntEntry(vBox, 3) )
                {
                    Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
                    fprintf( pFile, " %s ", pTypeNames[NtkId] );
                }
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) );
                fprintf( pFile, " %s ", pTypeNames[NtkId] );
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 7) );
            }
            else
            {
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
                fprintf( pFile, " %s ", pTypeNames[NtkId] );
                Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) );
            }
            fprintf( pFile, ";\n" );
278 279 280
        }
        else // box
        {
281
            fprintf( pFile, "  %s %s ( ", Prs_ObjGetName(p, NtkId), Prs_BoxName(p, i) ? Prs_ObjGetName(p, Prs_BoxName(p, i)) : "" );
282
            Prs_ManWriteVerilogArray2( pFile, p, vBox );
283
            fprintf( pFile, " );\n" );
284
        }
285
    }
286
}
287
static void Prs_ManWriteVerilogIos( FILE * pFile, Prs_Ntk_t * p, int SigType )
288 289
{
    int NameId, RangeId, i;
290 291 292 293 294 295
    char * pSigNames[4]   = { "inout", "input", "output", "wire" }; 
    Vec_Int_t * vSigs[4]  = { &p->vInouts,  &p->vInputs,  &p->vOutputs,  &p->vWires };
    Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR };
    if ( SigType == 3 )
        fprintf( pFile, "\n" );
    Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i )
296 297 298 299
    {
        fprintf( pFile, "  %s %s%s", pSigNames[SigType], Abc_LitIsCompl(RangeId) ? "signed " : "", RangeId ? Prs_ManWriteRange(p, Abc_Lit2Var(RangeId), 0) : "" );
        fprintf( pFile, "%s;\n", Prs_ObjGetName(p, NameId) );
    }
300
}
301
static void Prs_ManWriteVerilogIoOrder( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vOrder )
302
{
303 304
    int i, NameId;
    Vec_IntForEachEntry( vOrder, NameId, i )
305
        fprintf( pFile, "%s%s", Prs_ObjGetName(p, Abc_Lit2Var2(NameId)), i == Vec_IntSize(vOrder) - 1 ? "" : ", " );
306
}
307
static void Prs_ManWriteVerilogNtk( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames )
308 309 310
{
    int s;
    // write header
311
    fprintf( pFile, "module %s (\n    ", Prs_ObjGetName(p, p->iModuleName) );
312 313
    Prs_ManWriteVerilogIoOrder( pFile, p, &p->vOrder );
    fprintf( pFile, "\n  );\n" );
314 315
    // write declarations
    for ( s = 0; s < 4; s++ )
316
        Prs_ManWriteVerilogIos( pFile, p, s );
Alan Mishchenko committed
317
    fprintf( pFile, "\n" );
318
    // write objects
319
    Prs_ManWriteVerilogBoxes( pFile, p, pTypeNames );
Alan Mishchenko committed
320
    fprintf( pFile, "endmodule\n\n" );
321
}
322
void Prs_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs )
323
{
324
    char * pTypeNames[CBA_BOX_LAST];
325 326
    Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs); int i;
    FILE * pFile = fopen( pFileName, "wb" );
327 328 329 330 331
    if ( pFile == NULL )
    {
        printf( "Cannot open output file \"%s\".\n", pFileName );
        return;
    }
332
    Cba_ManCreatePrimMap( pTypeNames );
333 334
    fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
    Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
335
        Prs_ManWriteVerilogNtk( pFile, pNtk, pTypeNames );
336 337 338 339
    fclose( pFile );
}


340

341

342

343
static inline int Cba_NameIsLegalInVerilog( char * pName, int NameId )
344
{
345 346 347 348 349 350 351
    // identifier ::= simple_identifier | escaped_identifier
    // simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$]
    // escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space
    // white_space ::= space | tab | newline
    assert( pName != NULL && *pName != '\0' );
    if ( *pName == '\\' )
        return 1;
352 353
    if ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c
        return 0;
354 355 356 357 358 359 360 361 362
    if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' )
        return 0;
    while ( *(++pName) )
        if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' ) 
            return 0;
    return 1;
}
char * Cba_ObjGetName( Cba_Ntk_t * p, int i )
{
363 364 365
    char * pName = Cba_ObjNameStr(p, i);
    if ( pName == NULL )
        return pName;
366
    if ( Cba_NameIsLegalInVerilog(pName, Cba_ObjName(p, i)) )
367 368
        return pName;
    return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName );
369 370 371
}
char * Cba_FonGetName( Cba_Ntk_t * p, int i )
{
372 373 374
    char * pName = Cba_FonNameStr(p, i);
    if ( pName == NULL )
        return pName;
375 376
    if ( Cba_ObjType(p, Cba_FonObj(p, i)) == CBA_BOX_SLICE )
        return pName;
377
    if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, i)) )
378 379
        return pName;
    return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName );
380
}
381
char * Cba_ManGetSliceName( Cba_Ntk_t * p, int iFon, int RangeId )
382
{
383 384
    int Left  = Cba_NtkRangeLeft(p, RangeId);
    int Right = Cba_NtkRangeRight(p, RangeId);
385
    char * pName = Cba_FonNameStr(p, iFon);
386
    if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, iFon)) )
387 388 389 390 391 392 393 394 395 396
        if ( Left == Right )
            return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d]", pName, Right );
        else
            return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d:%d]", pName, Left, Right );
    else
        if ( Left == Right )
            return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d]", pName, Right );
        else
            return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d:%d]", pName, Left, Right );
}
397

398
void Cba_ManWriteFonRange( Cba_Ntk_t * p, int iFon )
399
{
400
    Vec_Str_t * vStr = &p->pDesign->vOut;
401
    if ( !iFon || Cba_FonIsConst(iFon) || (Cba_FonRangeSize(p, iFon) == 1 && Cba_FonRight(p, iFon) == 0) )
402
        return;
403 404
    if ( Cba_FonSigned(p, iFon) )
        Vec_StrPrintF( vStr, "signed " );
405
    Vec_StrPrintF( vStr, "[%d:%d] ", Cba_FonLeft(p, iFon), Cba_FonRight(p, iFon) );
406
}
407
void Cba_ManWriteFonName( Cba_Ntk_t * p, int iFon, int fInlineConcat, int fInput )
408
{
409
    extern void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj );
410
    Vec_Str_t * vStr = &p->pDesign->vOut;
411
    if ( !iFon || (!Cba_FonIsConst(iFon) && !Cba_FonName(p, iFon)) ) 
412 413
        Vec_StrPrintF( vStr, "Open_%d", Cba_NtkMan(p)->nOpens++ );
//        Vec_StrPrintF( vStr, "1\'b0" );
414 415
    else if ( fInlineConcat && !Cba_FonIsConst(iFon) && Cba_ObjIsConcat(p, Cba_FonObj(p, iFon)) )
        Cba_ManWriteConcat( p, Cba_FonObj(p, iFon) );
416
    else
417
    {
418
        int Range = fInput ? Cba_FonRangeSize( p, iFon ) : 0;
419 420
        if ( fInput && Range > 1 )
            Vec_StrPush( vStr, '{' );
421
        Vec_StrPrintStr( vStr, Cba_FonIsConst(iFon) ? Cba_NtkConst(p, Cba_FonConst(iFon)) : Cba_FonGetName(p, iFon) );
422 423 424
        if ( fInput && Range > 1 )
            Vec_StrPush( vStr, '}' );
    }
425
}
426
void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj )
427
{
428 429
    int i, iFin, iFon;
    Vec_Str_t * vStr = &p->pDesign->vOut;
430
    assert( Cba_ObjIsConcat(p, iObj) );
431 432
    Vec_StrPush( vStr, '{' );
    Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
433
    {
434
        Vec_StrPrintStr( vStr, i ? ", " : "" );
435
        Cba_ManWriteFonName( p, iFon, 1, 0 );
436
    }
437
    Vec_StrPush( vStr, '}' );
438
}
439
int Cba_ManWriteLineFile( Cba_Ntk_t * p, int iObj, int FileAttr, int LineAttr )
440
{
441 442 443
    Vec_Str_t * vStr = &p->pDesign->vOut;
    int FileId = 0, LineId = 0;
    if ( FileAttr && (FileId = Cba_ObjAttrValue(p, iObj, FileAttr)) )
444
    {
445
        LineId = Cba_ObjAttrValue(p, iObj, LineAttr);
Alan Mishchenko committed
446
        Vec_StrPrintF( vStr, "  // %s(%d)", Cba_NtkStr(p, FileId), LineId );
447
        return 1;
448
    }
449
    return 0;
450
}
451
void Cba_ManWriteVerilogNtk( Cba_Ntk_t * p, int fInlineConcat )
452
{
453
    Vec_Str_t * vStr = &p->pDesign->vOut;
454
    int i, k, iObj, iFin, iFon, StartPos, Status;
455 456 457 458 459 460
    int FileAttr = Cba_NtkStrId( p, "file" );
    int LineAttr = Cba_NtkStrId( p, "line" );
    int fUseNewLine = (int)(Cba_NtkPioNum(p) > 5);
    // mark PO fons
    Vec_Bit_t * vPoFons = Vec_BitStart( Cba_NtkFonNum(p)+1 );
    Cba_NtkForEachPoDriverFon( p, iObj, iFon, i )
461
        if ( Cba_FonIsReal(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj) )
462 463 464 465 466 467 468
            Vec_BitWriteEntry( vPoFons, iFon, 1 );
    // write header
    Vec_StrPrintStr( vStr, "module " );
    Vec_StrPrintStr( vStr, Cba_NtkName(p) );
    Vec_StrPrintStr( vStr, fUseNewLine ? " (\n    " : " ( " );
    StartPos = Vec_StrSize(vStr);
    Cba_NtkForEachPioOrder( p, iObj, i )
469
    {
470 471 472 473 474 475
        Vec_StrPrintStr( vStr, i ? ", " : "" );
        if ( Vec_StrSize(vStr) > StartPos + 70 )
        {
            StartPos = Vec_StrSize(vStr);
            Vec_StrPrintStr( vStr, "\n    " );
        }
476
        Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
477
    }
478 479 480 481 482
    Vec_StrPrintStr( vStr, fUseNewLine ? "\n  );" : " );" );
    Cba_ManWriteLineFile( p, 0, FileAttr, LineAttr );
    Vec_StrPrintStr( vStr, fUseNewLine ? "\n" : "\n\n" );
    // write inputs/outputs
    Cba_NtkForEachPioOrder( p, iObj, i )
483
    {
484
        int Offset = Vec_StrSize(vStr);
485 486 487
        Vec_StrPrintStr( vStr, "  " );
        Vec_StrPrintStr( vStr, Cba_ObjIsPi(p, iObj) ? "input " : "output " );
        Cba_ManWriteFonRange( p, Cba_ObjIsPi(p, iObj) ? Cba_ObjFon0(p, iObj) : Cba_ObjFinFon(p, iObj, 0) );
488
        Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
489
        Vec_StrPrintF( vStr, ";%*s", Offset + 40 - Vec_StrSize(vStr), "" );
490 491
        Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr );
        Vec_StrPush( vStr, '\n' );
492
    }
493 494 495
    Vec_StrPrintStr( vStr, "\n" );
    // write objects
    Cba_NtkForEachBox( p, iObj )
496
    {
497 498
//        char * pNameNtk = Cba_NtkName(p);
//        char * pNameInst = Cba_ObjGetName(p, iObj);
499
        int Type = Cba_ObjType(p, iObj);
500
        if ( Cba_ObjIsSlice(p, iObj) )
501
            continue;
502
        if ( fInlineConcat && Cba_ObjIsConcat(p, iObj) )
503
            continue;
504
        if ( Cba_ObjIsBoxUser(p, iObj) )
505
        {
506 507 508 509
            Cba_Ntk_t * pNtk = Cba_ObjNtk(p, iObj);
            // write output wire declarations
            Cba_ObjForEachFon( p, iObj, iFon, i )
            {
510 511
                if ( Vec_BitEntry(vPoFons, iFon) )
                    continue;
512 513
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, iFon );
514
                Cba_ManWriteFonName( p, iFon, 0, 0 );
515 516 517
                Vec_StrPrintStr( vStr, ";\n" );
            }
            // write box
518
            Vec_StrPrintStr( vStr, "  " );
519 520 521
            Vec_StrPrintStr( vStr, Cba_NtkName(pNtk) );
            Vec_StrPush( vStr, ' ' );
            if ( Cba_ObjName(p, iObj) )
522
                Vec_StrPrintF( vStr, "%s ", Cba_ObjGetName(p, iObj) );
523 524 525
            // write input binding
            Vec_StrPrintStr( vStr, "( " );
            Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
526
            {
527
                Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPi(pNtk, i)) );
528
                Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 );
529 530 531 532 533
                Vec_StrPush( vStr, ')' );
            }
            // write output binding
            Cba_ObjForEachFon( p, iObj, iFon, i )
            {
534
                Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPo(pNtk, i)) );
535
                Cba_ManWriteFonName( p, iFon, 0, 1 );
536
                Vec_StrPush( vStr, ')' );
537
            }
538
            Vec_StrPrintStr( vStr, ");" );
539
        }
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
        else if ( Type == CBA_BOX_RAMWC || Type == CBA_BOX_RAMBOX || Type == CBA_BOX_RAMR )
        {
            int Num = (Type == CBA_BOX_RAMWC) ? 0 : (Type == CBA_BOX_RAMR ? 1 : 2); // write / read / box
            char * pBoxName[3] = { "RAM_WRITE", "RAM_READ", "RAM_BOX" };
            char * pOutputs[3] = { "ram", "rdata", "out" };
            char * pInputs[3][4] = {  {"clk", "wen", "waddr", "wdata"},  {"ren", "raddr", "ram"},   {"in0", "in1", "in2", "in3"} };
            // write declaration for the output
            int iFonOut = Cba_ObjFon0(p, iObj);
            if ( Vec_BitEntry(vPoFons, iFonOut) ) 
                Vec_StrPrintStr( vStr, "  assign " );
            else
            {
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, iFonOut );
            }
            Cba_ManWriteFonName( p, iFonOut, 0, 0 );
            Vec_StrPrintStr( vStr, ";\n" );
            // write box
            Vec_StrPrintF( vStr, "  %s( ", pBoxName[Num] );
            Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
            {
                Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", pInputs[Num][i] );
                Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 );
                Vec_StrPush( vStr, ')' );
            }
            Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", pOutputs[Num] );
            Cba_ManWriteFonName( p, iFonOut, 0, 1 );
            Vec_StrPrintStr( vStr, ") );" );
        }
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
        else if ( Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL )
        {
            int fUseSel = Type == CBA_BOX_SEL;
            int nBits   = fUseSel ? Cba_ObjFinNum(p, iObj) - 1 : Abc_Base2Log(Cba_ObjFinNum(p, iObj) - 1);
            int iFonIn  = Cba_ObjFinFon(p, iObj, 0);
            int iFonOut = Cba_ObjFon0(p, iObj);
            // function [15:0] res;
            Vec_StrPrintStr( vStr, "  function " );
            Cba_ManWriteFonRange( p, iFonOut );
            Vec_StrPrintStr( vStr, "_func_" );
            Cba_ManWriteFonName( p, iFonOut, 0, 0 );
            Vec_StrPrintStr( vStr, ";\n" );
            // input [1:0] s;
            Vec_StrPrintStr( vStr, "    input " );
            Cba_ManWriteFonRange( p, iFonIn );
            Vec_StrPrintStr( vStr, "s;\n" );
            // input [15:0] d0, d1, d2, d3;
            Vec_StrPrintStr( vStr, "    input " );
            Cba_ManWriteFonRange( p, iFonOut );
            Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
            {
                if ( i == 0 ) continue;
591
                Vec_StrPrintF( vStr, "%sd%d", i > 1 ? ", " : "", i-1 );
592 593 594 595 596 597 598 599 600 601 602
            }
            Vec_StrPrintStr( vStr, ";\n" );
            // casez (s)
            Vec_StrPrintStr( vStr, "    casez(s)" );
            if ( fUseSel )
                Vec_StrPrintStr( vStr, "  // synopsys full_case parallel_case" );
            Vec_StrPrintStr( vStr, "\n" );
            // 2'b00: res = b[15:0];
            Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
            {
                if ( i == 0 ) continue;
603
                Vec_StrPrintF( vStr, "      %d\'b", nBits );
604 605 606 607 608 609 610 611 612 613 614 615
                if ( fUseSel )
                {
                    Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + nBits, '?' );
                    Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i, '1' );
                }
                else
                {
                    for ( k = nBits-1; k >= 0; k-- )
                        Vec_StrPrintNum( vStr, ((i-1) >> k) & 1 );
                }
                Vec_StrPrintStr( vStr, ": _func_" );
                Cba_ManWriteFonName( p, iFonOut, 0, 0 );
616
                Vec_StrPrintF( vStr, " = d%d;\n", i-1 );
617 618 619 620 621
            }
            Vec_StrPrintStr( vStr, "    endcase\n" );
            Vec_StrPrintStr( vStr, "  endfunction\n" );
            // assign z = res(a, b, s);
            if ( Vec_BitEntry(vPoFons, iFonOut) ) 
622 623 624 625
                Vec_StrPrintStr( vStr, "  assign " );
            else
            {
                Vec_StrPrintStr( vStr, "  wire " );
626
                Cba_ManWriteFonRange( p, iFonOut );
627
            }
628 629 630 631 632
            Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, " = _func_" );
            Cba_ManWriteFonName( p, iFonOut, 0, 0 );
            Vec_StrPrintStr( vStr, " ( " );
            Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
633
            {
634 635 636 637 638
                Vec_StrPrintStr( vStr, i ? ", " : "" );
                Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 );
            }
            Vec_StrPrintStr( vStr, " );" );
        }
639 640 641 642
        else if ( Type == CBA_BOX_DEC )
        {
            int iFonIn   = Cba_ObjFinFon(p, iObj, 0);
            int iFonOut  = Cba_ObjFon0(p, iObj);
643 644
            int nBitsIn  = Cba_FonRangeSize(p, iFonIn);
            int nBitsOut = Cba_FonRangeSize(p, iFonOut);
645 646 647 648 649 650 651 652 653 654 655 656 657 658
            assert( (1 << nBitsIn) == nBitsOut );
            // function [15:0] res;
            Vec_StrPrintStr( vStr, "  function " );
            Cba_ManWriteFonRange( p, iFonOut );
            Vec_StrPrintStr( vStr, "_func_" );
            Cba_ManWriteFonName( p, iFonOut, 0, 0 );
            Vec_StrPrintStr( vStr, ";\n" );
            // input [1:0] i;
            Vec_StrPrintStr( vStr, "    input " );
            Cba_ManWriteFonRange( p, iFonIn );
            Vec_StrPrintStr( vStr, "i;\n" );
            // casez (i)
            Vec_StrPrintStr( vStr, "    casez(i)\n" );
            // 2'b00: res = 4'b0001;
659
            for ( i = 0; i < (1 << nBitsIn); i++ )
660
            {
661 662 663
                Vec_StrPrintF( vStr, "      %d\'b", nBitsIn );
                for ( k = nBitsIn-1; k >= 0; k-- )
                    Vec_StrPrintNum( vStr, (i >> k) & 1 );
664 665
                Vec_StrPrintStr( vStr, ": _func_" );
                Cba_ManWriteFonName( p, iFonOut, 0, 0 );
666
                Vec_StrPrintF( vStr, " = %d\'b%0*d;\n", nBitsOut, nBitsOut, 0 );
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
                Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i - 3, '1' );
            }
            Vec_StrPrintStr( vStr, "    endcase\n" );
            Vec_StrPrintStr( vStr, "  endfunction\n" );
            // assign z = res(i, o);
            if ( Vec_BitEntry(vPoFons, iFonOut) ) 
                Vec_StrPrintStr( vStr, "  assign " );
            else
            {
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, iFonOut );
            }
            Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, " = _func_" );
            Cba_ManWriteFonName( p, iFonOut, 0, 0 );
            Vec_StrPrintStr( vStr, " ( " );
            Cba_ManWriteFonName( p, iFonIn, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, " );" );
         }
686 687 688 689 690
        else if ( Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS )
        {
            int fUseFlop = Type == CBA_BOX_DFFRS;
            int iFonQ    = Cba_ObjFon0(p, iObj);
            int iFonD    = Cba_ObjFinFon(p, iObj, 0);
691 692
            int iFonSet  = Cba_ObjFinFon(p, iObj, 1);
            int iFonRst  = Cba_ObjFinFon(p, iObj, 2);
693
            int iFonC    = Cba_ObjFinFon(p, iObj, 3);
694 695
            int Range    = Cba_FonRangeSize( p, iFonQ );
            assert( Cba_FonRangeSize(p, iFonSet) == 1 && Cba_FonRangeSize(p, iFonRst) == 1 );
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
            // reg    [3:0] Q;
            Vec_StrPrintStr( vStr, "  reg " );
            Cba_ManWriteFonRange( p, iFonQ );
            Cba_ManWriteFonName( p, iFonQ, 0, 0 );
            Vec_StrPrintStr( vStr, ";\n" );
            // always @(posedge C or posedge PRE)
            Vec_StrPrintStr( vStr, "  always @(" );
            if ( fUseFlop )
                Vec_StrPrintStr( vStr, "posedge " );
            Cba_ManWriteFonName( p, iFonC, 0, 0 );
            if ( !fUseFlop )
            {
                Vec_StrPrintStr( vStr, " or " );
                Cba_ManWriteFonName( p, iFonD, 0, 0 );
            }
            if ( iFonSet > 0 )
            {
                Vec_StrPrintStr( vStr, " or " );
                if ( fUseFlop )
                    Vec_StrPrintStr( vStr, "posedge " );
                Cba_ManWriteFonName( p, iFonSet, 0, 0 );
            }
            if ( iFonRst > 0 )
            {
                Vec_StrPrintStr( vStr, " or " );
                if ( fUseFlop )
                    Vec_StrPrintStr( vStr, "posedge " );
                Cba_ManWriteFonName( p, iFonRst, 0, 0 );
            }
            Vec_StrPrintStr( vStr, ")\n" );
            //  if (Set)  Q <= 4'b1111;
727
            if ( iFonSet > 0 )
728 729 730 731 732 733
            {
                Vec_StrPrintStr( vStr, "    if (" );
                Cba_ManWriteFonName( p, iFonSet, 0, 0 );
                Vec_StrPrintStr( vStr, ")  " );
                Cba_ManWriteFonName( p, iFonQ, 0, 0 );
                Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
734
                // value 1
735 736 737 738
                Vec_StrPrintNum( vStr, Range );
                Vec_StrPrintStr( vStr, "\'b" );
                Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '1' );
                Vec_StrPrintStr( vStr, ";\n" );
739
//                Vec_StrPrintF( vStr, "\'b1" );
740
            }
741
            if ( iFonRst > 0 )
742
            {
743
                Vec_StrPrintStr( vStr, iFonSet > 0 ? "    else if (" : "    if (" );
744 745 746 747
                Cba_ManWriteFonName( p, iFonRst, 0, 0 );
                Vec_StrPrintStr( vStr, ")  " );
                Cba_ManWriteFonName( p, iFonQ, 0, 0 );
                Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
748
                // value 0
749 750 751 752
                Vec_StrPrintNum( vStr, Range );
                Vec_StrPrintStr( vStr, "\'b" );
                Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '0' );
                Vec_StrPrintStr( vStr, ";\n" );
753
//                Vec_StrPrintF( vStr, "\'b0" );
754
            }
755
            Vec_StrPrintStr( vStr, (iFonSet > 0 || iFonRst > 0) ? "    else " : "    " );
756 757 758 759 760 761 762 763 764 765 766
            if ( !fUseFlop )
            {
                Vec_StrPrintStr( vStr, "    if (" );
                Cba_ManWriteFonName( p, iFonC, 0, 0 );
                Vec_StrPrintStr( vStr, ")  " );
            }
            Cba_ManWriteFonName( p, iFonQ, 0, 0 );
            Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
            Cba_ManWriteFonName( p, iFonD, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, ";" );
        }
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
        else if ( Type == CBA_BOX_DFFCPL )
        {
            // CPL_FF#32 inst_reg( .d(s1), .arstval(s2), .arst(s3), .clk(s4), .q(s5), .qbar(s6) );
            int iFon0 = Cba_ObjFon0(p, iObj);
            int iFon1 = Cba_ObjFon(p, iObj, 1);
            int Range = Cba_FonRangeSize( p, iFon0 );
            if ( !Vec_BitEntry(vPoFons, iFon0) )
            {
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, iFon0 );
                Cba_ManWriteFonName( p, iFon0, 0, 0 );
                Vec_StrPrintStr( vStr, ";\n" );
            }
            if ( !Vec_BitEntry(vPoFons, iFon1) && Cba_FonName(p, iFon1) )
            {
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, iFon1 );
                Cba_ManWriteFonName( p, iFon1, 0, 0 );
                Vec_StrPrintStr( vStr, ";\n" );
            }
            Vec_StrPrintStr( vStr, "  CPL_FF" );
            if ( Range > 1 )
                Vec_StrPrintF( vStr, "#%d", Range );
            Vec_StrPrintStr( vStr, " " );
            if ( Cba_ObjName(p, iObj) )
                Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
            Vec_StrPrintStr( vStr, " ( .d(" );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, "), .arstval(" );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, "), .arst(" );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, "), .clk(" );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 3), fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, "), .q(" );
            Cba_ManWriteFonName( p, iFon0, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, "), .qbar(" );
            if ( Cba_FonName(p, iFon1) )
                Cba_ManWriteFonName( p, iFon1, fInlineConcat, 0 );
            Vec_StrPrintStr( vStr, ") );" );
        }
808 809 810 811 812 813 814 815
        else if ( Type == CBA_BOX_ADD )
        {
            int iFon0 = Cba_ObjFon0(p, iObj);
            int iFon1 = Cba_ObjFon(p, iObj, 1);
            // write outputs
            if ( Cba_FonName(p, iFon1) )
            {
                if ( !Vec_BitEntry(vPoFons, iFon0) )
816
                {
817 818 819 820
                    Vec_StrPrintStr( vStr, "  wire " );
                    Cba_ManWriteFonRange( p, iFon0 );
                    Cba_ManWriteFonName( p, iFon0, 0, 0 );
                    Vec_StrPrintStr( vStr, ";\n" );
821
                }
822 823 824 825 826 827 828 829 830 831 832 833
                if ( !Vec_BitEntry(vPoFons, iFon1) )
                {
                    Vec_StrPrintStr( vStr, "  wire " );
                    Cba_ManWriteFonRange( p, iFon1 );
                    Cba_ManWriteFonName( p, iFon1, 0, 0 );
                    Vec_StrPrintStr( vStr, ";\n" );
                }
                Vec_StrPrintStr( vStr, "  assign {" );
                Cba_ManWriteFonName( p, iFon1, 0, 0 );
                Vec_StrPrintStr( vStr, ", " );
                Cba_ManWriteFonName( p, iFon0, 0, 0 );
                Vec_StrPrintStr( vStr, "} = " );
834
            }
835
            else
836
            {
837 838 839
                if ( Vec_BitEntry(vPoFons, iFon0) ) 
                    Vec_StrPrintStr( vStr, "  assign " );
                else
840
                {
841 842
                    Vec_StrPrintStr( vStr, "  wire " );
                    Cba_ManWriteFonRange( p, iFon0 );
843
                }
844 845 846 847
                Cba_ManWriteFonName( p, iFon0, 0, 0 );
                Vec_StrPrintStr( vStr, " = " );
            }
            // write carry-in
848
            if ( Cba_ObjFinFon(p, iObj, 0) && Cba_ObjFinFon(p, iObj, 0) != Cba_FonFromConst(1) )
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
            {
                Vec_StrPush( vStr, ' ' );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
                Vec_StrPush( vStr, ' ' );
                Vec_StrPrintStr( vStr, "+" );
            }
            Vec_StrPush( vStr, ' ' );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
            Vec_StrPush( vStr, ' ' );
            Vec_StrPrintStr( vStr, "+" );
            Vec_StrPush( vStr, ' ' );
            Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
            Vec_StrPush( vStr, ';' );
        }
        else
        {
            if ( Vec_BitEntry(vPoFons, Cba_ObjFon0(p, iObj)) ) 
                Vec_StrPrintStr( vStr, "  assign " );
            else
            {
                Vec_StrPrintStr( vStr, "  wire " );
                Cba_ManWriteFonRange( p, Cba_ObjFon0(p, iObj) );
            }
            Cba_ManWriteFonName( p, Cba_ObjFon0(p, iObj), 0, 0 );
            Vec_StrPrintStr( vStr, " = " );
874 875
            if ( Cba_ObjIsConcat(p, iObj) )
                Cba_ManWriteConcat( p, iObj );
876 877 878 879 880 881 882 883
            else if ( Type == CBA_BOX_MUX )
            {
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
                Vec_StrPrintStr( vStr, " ? " );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
                Vec_StrPrintStr( vStr, " : " );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
            }
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
            else if ( Type == CBA_BOX_ROTL || Type == CBA_BOX_ROTR )
            {
                //  wire [27:0] s4960 = (s57 >> 17) | (s57 << 11);
                int Range = Cba_FonRangeSize( p, Cba_ObjFon0(p, iObj) );
                int iFinFon1 = Cba_ObjFinFon(p, iObj, 1);
                Vec_StrPush( vStr, '(' );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
                Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " << " : " >> " );
                if ( Cba_FonIsConst(iFinFon1) )
                    Vec_StrPrintNum( vStr, Cba_FonConst(iFinFon1) );
                else
                    Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
                Vec_StrPrintStr( vStr, ") | (" );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
                Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " >> " : " << " );
                if ( Cba_FonIsConst(iFinFon1) )
                    Vec_StrPrintNum( vStr, Range - Cba_FonConst(iFinFon1) );
                else
                {
                    Vec_StrPush( vStr, '(' );
                    Vec_StrPrintNum( vStr, Range );
                    Vec_StrPrintStr( vStr, " - " );
                    Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
                    Vec_StrPush( vStr, ')' );
                }
                Vec_StrPush( vStr, ')' );
            }
911 912 913 914 915 916 917 918 919
            else if ( Type == CBA_BOX_LTHAN )
            {
                int fLessThan = (Cba_ObjFinFon(p, iObj, 0) == Cba_FonFromConst(1)); // const0
                Vec_StrPush( vStr, ' ' );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
                Vec_StrPush( vStr, ' ' );
                Vec_StrPrintStr( vStr, fLessThan ? "<" : "<=" );
                Vec_StrPush( vStr, ' ' );
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
920
            }
921
            else if ( Cba_TypeIsUnary((Cba_ObjType_t)Type) )
922 923
            {
                Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) );
924
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
925
            }
926
            else if ( Cba_NtkTypeName(p, Type) ) // binary operation
927
            {
928 929 930
                int fCompl = (Type == CBA_BOX_NAND || Type == CBA_BOX_NOR || Type == CBA_BOX_XNOR);
                if ( fCompl )
                    Vec_StrPrintStr( vStr, "!(" );
931
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
932 933 934
                Vec_StrPush( vStr, ' ' );
                Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) );
                Vec_StrPush( vStr, ' ' );
935
                Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
936 937
                if ( fCompl )
                    Vec_StrPrintStr( vStr, ")" );
938 939 940
            }
            else // unknown
            {
941
                char * pName = Cba_FonGetName(p, Cba_ObjFon0(p, iObj));
942
                Vec_StrPrintStr( vStr, "<unknown operator>" );
943
                printf( "Cba_ManWriteVerilog(): In module \"%s\", cannot write object \"%s\" with output name \"%s\".\n", Cba_NtkName(p), Cba_ObjGetName(p, iObj), pName );
944
            }
945
            Vec_StrPush( vStr, ';' );
946
        }
947 948 949
        // write attributes
        Status = Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr );
        if ( !Cba_ObjIsBoxUser(p, iObj) && Cba_ObjName(p, iObj) )
950
        {
951 952 953
            if ( !Status )
                Vec_StrPrintStr( vStr, "  //" );
            Vec_StrPrintStr( vStr, " name=" );
954
            Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
955
        }
956
        Vec_StrPush( vStr, '\n' );
957
    }
958 959
    // write remaining outputs
    Cba_NtkForEachPo( p, iObj, i )
960
    {
961
        iFon = Cba_ObjFinFon(p, iObj, 0);
962
        if ( !iFon || (!Cba_FonIsConst(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj)) ) // already written
963 964
            continue;
        Vec_StrPrintStr( vStr, "  assign " );
965
        Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
966
        Vec_StrPrintStr( vStr, " = " );
967
        Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 );
968 969
        Vec_StrPush( vStr, ';' );
        Vec_StrPush( vStr, '\n' );
970 971
    }
    Vec_StrPrintStr( vStr, "\n" );
972
    Vec_StrPrintStr( vStr, "endmodule\n\n" );
973
    Vec_BitFree( vPoFons );
974
}
975
void Cba_ManWriteVerilog( char * pFileName, Cba_Man_t * p, int fInlineConcat )
976
{
977
    Cba_Ntk_t * pNtk; int i;
978 979 980 981 982 983
    // check the library
    if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
    {
        printf( "Genlib library used in the mapped design is not longer a current library.\n" );
        return;
    }
984
    Cba_ManCreatePrimMap( p->pTypeNames );
985
    // derive the stream
986
    p->nOpens = 1;
987 988 989 990 991 992 993
    Vec_StrClear( &p->vOut );
    Vec_StrClear( &p->vOut2 );
    Vec_StrPrintStr( &p->vOut, "// Design \"" );
    Vec_StrPrintStr( &p->vOut, Cba_ManName(p) );
    Vec_StrPrintStr( &p->vOut, "\" written via CBA package in ABC on " );
    Vec_StrPrintStr( &p->vOut, Extra_TimeStamp() );
    Vec_StrPrintStr( &p->vOut, "\n\n" );
994
    Cba_ManForEachNtk( p, pNtk, i )
995
        Cba_ManWriteVerilogNtk( pNtk, fInlineConcat );
996
    // dump into file
997
    if ( Vec_StrSize(&p->vOut) > 0 )
998 999 1000 1001 1002 1003
    {
        FILE * pFile = fopen( pFileName, "wb" );
        if ( pFile == NULL )
            printf( "Cannot open file \"%s\" for writing.\n", pFileName );
        else
        {
1004
            fwrite( Vec_StrArray(&p->vOut), 1, Vec_StrSize(&p->vOut), pFile );
1005 1006 1007
            fclose( pFile );
        }
    }
1008
}
1009 1010 1011 1012 1013 1014 1015 1016

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END