mirror of https://github.com/YosysHQ/abc.git
Added support of word-level MUXes represented as 'always'-statements.
This commit is contained in:
parent
d9b5aa49f7
commit
a4d5a9b5bc
|
|
@ -80,6 +80,15 @@ int Wlc_BlastGetConst( int * pNum, int nNum )
|
|||
return -1;
|
||||
return Res;
|
||||
}
|
||||
int Wlc_NtkMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift )
|
||||
{
|
||||
int iLit0, iLit1;
|
||||
if ( nCtrl == 0 )
|
||||
return Vec_IntEntry( vData, Shift );
|
||||
iLit0 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift );
|
||||
iLit1 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) );
|
||||
return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -333,7 +342,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
Vec_Int_t * vBits, * vTemp0, * vTemp1, * vTemp2, * vRes;
|
||||
int nBits = Wlc_NtkPrepareBits( p );
|
||||
int nRange, nRange0, nRange1, nRange2;
|
||||
int i, k, b, iLit, * pFans0, * pFans1, * pFans2;
|
||||
int i, k, b, iFanin, iLit, * pFans0, * pFans1, * pFans2;
|
||||
vBits = Vec_IntAlloc( nBits );
|
||||
vTemp0 = Vec_IntAlloc( 1000 );
|
||||
vTemp1 = Vec_IntAlloc( 1000 );
|
||||
|
|
@ -346,7 +355,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
// create primary inputs
|
||||
Wlc_NtkForEachObj( p, pObj, i )
|
||||
{
|
||||
// char * pName = Wlc_ObjName(p, i);
|
||||
char * pName = Wlc_ObjName(p, i);
|
||||
nRange = Wlc_ObjRange( pObj );
|
||||
nRange0 = Wlc_ObjFaninNum(pObj) > 0 ? Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ) : -1;
|
||||
nRange1 = Wlc_ObjFaninNum(pObj) > 1 ? Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ) : -1;
|
||||
|
|
@ -362,9 +371,18 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
}
|
||||
else if ( pObj->Type == WLC_OBJ_PO || pObj->Type == WLC_OBJ_BUF )
|
||||
{
|
||||
// assert( nRange <= nRange0 );
|
||||
for ( k = 0; k < nRange; k++ )
|
||||
Vec_IntPush( vRes, k < nRange0 ? pFans0[k] : 0 );
|
||||
if ( pObj->Type == WLC_OBJ_BUF && pObj->Signed && !Wlc_ObjFanin0(p, pObj)->Signed ) // unsign->sign
|
||||
{
|
||||
int nRangeMax = Abc_MaxInt( nRange0, nRange );
|
||||
int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, 0 );
|
||||
Wlc_BlastMinus( pNew, pArg0, nRange, vRes );
|
||||
}
|
||||
else
|
||||
{
|
||||
// assert( nRange <= nRange0 );
|
||||
for ( k = 0; k < nRange; k++ )
|
||||
Vec_IntPush( vRes, k < nRange0 ? pFans0[k] : 0 );
|
||||
}
|
||||
}
|
||||
else if ( pObj->Type == WLC_OBJ_CONST )
|
||||
{
|
||||
|
|
@ -374,9 +392,19 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
}
|
||||
else if ( pObj->Type == WLC_OBJ_MUX )
|
||||
{
|
||||
assert( nRange0 == 1 && nRange1 == nRange && nRange2 == nRange );
|
||||
for ( k = 0; k < nRange; k++ )
|
||||
Vec_IntPush( vRes, Gia_ManHashMux(pNew, pFans0[0], pFans1[k], pFans2[k]) );
|
||||
assert( 1 + (1 << nRange0) == Wlc_ObjFaninNum(pObj) );
|
||||
for ( b = 0; b < nRange; b++ )
|
||||
{
|
||||
Vec_IntClear( vTemp0 );
|
||||
Wlc_ObjForEachFanin( pObj, iFanin, k )
|
||||
{
|
||||
if ( !k ) continue;
|
||||
assert( nRange == Wlc_ObjRange(Wlc_NtkObj(p, iFanin)) );
|
||||
pFans1 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) );
|
||||
Vec_IntPush( vTemp0, pFans1[b] );
|
||||
}
|
||||
Vec_IntPush( vRes, Wlc_NtkMuxTree_rec(pNew, pFans0, nRange0, vTemp0, 0) );
|
||||
}
|
||||
}
|
||||
else if ( pObj->Type == WLC_OBJ_SHIFT_R || pObj->Type == WLC_OBJ_SHIFT_RA )
|
||||
{
|
||||
|
|
@ -487,12 +515,14 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
else if ( pObj->Type == WLC_OBJ_COMP_LESS || pObj->Type == WLC_OBJ_COMP_MOREEQU ||
|
||||
pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU )
|
||||
{
|
||||
int nRangeMax = Abc_MaxInt( nRange0, nRange1 );
|
||||
int * pArg0 = Wlc_VecLoadFanins( vRes, pFans0, nRange0, nRangeMax, Wlc_ObjFanin0(p, pObj)->Signed );
|
||||
int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjFanin1(p, pObj)->Signed );
|
||||
int fSwap = (pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU);
|
||||
int fCompl = (pObj->Type == WLC_OBJ_COMP_MOREEQU || pObj->Type == WLC_OBJ_COMP_LESSEQU);
|
||||
assert( nRange == 1 );
|
||||
assert( nRange0 == nRange1 );
|
||||
if ( fSwap ) ABC_SWAP( int *, pFans0, pFans1 );
|
||||
iLit = Wlc_BlastLess( pNew, pFans0, pFans1, nRange0 );
|
||||
iLit = Wlc_BlastLess( pNew, pFans0, pFans1, nRangeMax );
|
||||
iLit = Abc_LitNotCond( iLit, fCompl );
|
||||
Vec_IntFill( vRes, 1, iLit );
|
||||
}
|
||||
|
|
@ -516,15 +546,17 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p )
|
|||
}
|
||||
else if ( pObj->Type == WLC_OBJ_ARI_DIVIDE || pObj->Type == WLC_OBJ_ARI_MODULUS )
|
||||
{
|
||||
int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange, Wlc_ObjFanin0(p, pObj)->Signed );
|
||||
int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRange, Wlc_ObjFanin1(p, pObj)->Signed );
|
||||
assert( nRange0 <= nRange && nRange1 <= nRange );
|
||||
Wlc_BlastDivider( pNew, pArg0, nRange, pArg1, nRange, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes );
|
||||
int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) );
|
||||
int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjFanin0(p, pObj)->Signed );
|
||||
int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjFanin1(p, pObj)->Signed );
|
||||
Wlc_BlastDivider( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes );
|
||||
Vec_IntShrink( vRes, nRange );
|
||||
}
|
||||
else if ( pObj->Type == WLC_OBJ_ARI_MINUS )
|
||||
{
|
||||
assert( nRange0 == nRange );
|
||||
Wlc_BlastMinus( pNew, pFans0, nRange0, vRes );
|
||||
int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange, Wlc_ObjFanin0(p, pObj)->Signed );
|
||||
assert( nRange0 <= nRange );
|
||||
Wlc_BlastMinus( pNew, pArg0, nRange, vRes );
|
||||
}
|
||||
else if ( pObj->Type == WLC_OBJ_TABLE )
|
||||
Wlc_BlastTable( pNew, Wlc_ObjTable(p, pObj), pFans0, nRange0, nRange, vRes );
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ static inline char * Wlc_PrsFindName( char * pStr, char ** ppPlace )
|
|||
}
|
||||
static inline char * Wlc_PrsReadConstant( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins, int * pRange, int * pSigned )
|
||||
{
|
||||
int nDigits, nBits = atoi( pStr );
|
||||
int i, nDigits, nBits = atoi( pStr );
|
||||
*pRange = -1;
|
||||
*pSigned = 0;
|
||||
pStr = Wlc_PrsSkipSpaces( pStr );
|
||||
|
|
@ -418,6 +418,18 @@ static inline char * Wlc_PrsReadConstant( Wlc_Prs_t * p, char * pStr, Vec_Int_t
|
|||
*pSigned = 1;
|
||||
pStr++;
|
||||
}
|
||||
if ( pStr[1] == 'b' )
|
||||
{
|
||||
Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
if ( pStr[2+i] == '1' )
|
||||
Abc_InfoSetBit( (unsigned *)Vec_IntArray(vFanins), i );
|
||||
else if ( pStr[2+i] != '0' )
|
||||
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Wrong digit in binary constant \"%c\".", pStr[2+i] );
|
||||
*pRange = nBits;
|
||||
pStr += 2 + nBits;
|
||||
return pStr;
|
||||
}
|
||||
if ( pStr[1] != 'h' )
|
||||
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Expecting hexadecimal constant and not \"%c\".", pStr[1] );
|
||||
Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 );
|
||||
|
|
@ -652,6 +664,8 @@ int Wlc_PrsReadDeclaration( Wlc_Prs_t * p, char * pStart )
|
|||
pStart = Wlc_PrsSkipSpaces( pStart );
|
||||
if ( Wlc_PrsStrCmp( pStart, "wire" ) )
|
||||
pStart += strlen("wire");
|
||||
else if ( Wlc_PrsStrCmp( pStart, "reg" ) )
|
||||
pStart += strlen("reg");
|
||||
// read 'signed'
|
||||
pStart = Wlc_PrsFindWord( pStart, "signed", &Signed );
|
||||
// read range
|
||||
|
|
@ -696,6 +710,7 @@ int Wlc_PrsDerive( Wlc_Prs_t * p )
|
|||
// go through the directives
|
||||
Wlc_PrsForEachLine( p, pStart, i )
|
||||
{
|
||||
startword:
|
||||
if ( Wlc_PrsStrCmp( pStart, "module" ) )
|
||||
{
|
||||
// get module name
|
||||
|
|
@ -770,7 +785,7 @@ int Wlc_PrsDerive( Wlc_Prs_t * p )
|
|||
break;
|
||||
}
|
||||
// these are read as part of the interface
|
||||
else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) )
|
||||
else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" ) )
|
||||
{
|
||||
if ( !Wlc_PrsReadDeclaration( p, pStart ) )
|
||||
return 0;
|
||||
|
|
@ -833,6 +848,84 @@ int Wlc_PrsDerive( Wlc_Prs_t * p )
|
|||
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
|
||||
}
|
||||
}
|
||||
else if ( Wlc_PrsStrCmp( pStart, "always" ) )
|
||||
{
|
||||
// THIS IS A HACK TO DETECT tables
|
||||
int NameId, NameIdOut = -1, fFound;
|
||||
// find control
|
||||
pStart = Wlc_PrsFindWord( pStart, "case", &fFound );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
|
||||
// read the name
|
||||
pStart = Wlc_PrsFindSymbol( pStart, '(' );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
|
||||
pStart = Wlc_PrsFindSymbol( pStart+1, '(' );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
|
||||
pStart = Wlc_PrsFindName( pStart+1, &pName );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
|
||||
if ( !fFound )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
|
||||
Vec_IntClear( p->vFanins );
|
||||
Vec_IntPush( p->vFanins, NameId );
|
||||
// read data inputs
|
||||
while ( 1 )
|
||||
{
|
||||
// find opening
|
||||
pStart = Wlc_PrsFindSymbol( pStart, ':' );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find colon in the case statement." );
|
||||
// find output name
|
||||
pStart = Wlc_PrsFindName( pStart+1, &pName );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." );
|
||||
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
|
||||
if ( !fFound )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
|
||||
// find equality
|
||||
pStart = Wlc_PrsFindSymbol( pStart, '=' );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find equality in the case statement." );
|
||||
// find input name
|
||||
pStart = Wlc_PrsSkipSpaces( pStart+1 );
|
||||
pStart = Wlc_PrsReadName( p, pStart, p->vFanins );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside case statement." );
|
||||
// get next line and check its opening character
|
||||
pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i));
|
||||
pStart = Wlc_PrsSkipSpaces( pStart );
|
||||
if ( Wlc_PrsIsDigit(pStart) )
|
||||
continue;
|
||||
if ( Wlc_PrsStrCmp( pStart, "default" ) )
|
||||
{
|
||||
printf( "Ignoring default in Line %d.\n", i );
|
||||
pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i));
|
||||
}
|
||||
// find closing
|
||||
pStart = Wlc_PrsFindWord( pStart, "endcase", &fFound );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
|
||||
// find closing
|
||||
pStart = Wlc_PrsFindWord( pStart, "end", &fFound );
|
||||
if ( pStart == NULL )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
|
||||
pStart = Wlc_PrsSkipSpaces( pStart );
|
||||
break;
|
||||
}
|
||||
// check range of the control
|
||||
{
|
||||
Wlc_Obj_t * pObj = Wlc_NtkObj( p->pNtk, Vec_IntEntry(p->vFanins, 0) );
|
||||
if ( (1 << Wlc_ObjRange(pObj)) != Vec_IntSize(p->vFanins) - 1 )
|
||||
return Wlc_PrsWriteErrorMessage( p, pStart, "The number of values in the case statement is wrong.", pName );
|
||||
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
|
||||
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_MUX );
|
||||
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
|
||||
goto startword;
|
||||
}
|
||||
}
|
||||
// else if ( Wlc_PrsStrCmp( pStart, "CPL_FF" ) )
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -178,6 +178,30 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p )
|
|||
else
|
||||
fprintf( pFile, "(%s << %d) | (%s >> %d)", pName0, Num0, pName0, Num1 );
|
||||
}
|
||||
else if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 )
|
||||
{
|
||||
fprintf( pFile, " reg %s ;\n", pName );
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "always @( " );
|
||||
Wlc_ObjForEachFanin( pObj, iFanin, k )
|
||||
fprintf( pFile, "%s%s", k ? " or ":"", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) );
|
||||
fprintf( pFile, " )\n" );
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "begin\n" );
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "case ( %s )\n", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 0)) );
|
||||
Wlc_ObjForEachFanin( pObj, iFanin, k )
|
||||
{
|
||||
if ( !k ) continue;
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "%d : %s = %s ;\n", k-1, pName, Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) );
|
||||
}
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "endcase\n" );
|
||||
fprintf( pFile, " " );
|
||||
fprintf( pFile, "end\n" );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( pFile, " wire %s %-16s = ", Range, Wlc_ObjName(p, i) );
|
||||
|
|
|
|||
Loading…
Reference in New Issue