mirror of https://github.com/YosysHQ/abc.git
357 lines
13 KiB
C
357 lines
13 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [cbaBuild.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Verilog parser.]
|
|
|
|
Synopsis [Parses several flavors of word-level Verilog.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - November 29, 2014.]
|
|
|
|
Revision [$Id: cbaBuild.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "cba.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
Elaboration input data:
|
|
Vec_Int_t vInputs; // inputs (used by parser to store signals as NameId)
|
|
Vec_Int_t vOutputs; // outputs (used by parser to store signals as NameId)
|
|
Vec_Int_t vTypes; // types (used by parser to store Cba_PrsType_t)
|
|
Vec_Int_t vFuncs; // functions (used by parser to store function)
|
|
Vec_Int_t vFanins; // fanins (used by parser to store fanin/fanout signals as NameId)
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
// replaces NameIds of formal names by their index in the box model
|
|
void Cba_BoxRemap( Cba_Ntk_t * pNtk, int iBox, Vec_Int_t * vMap )
|
|
{
|
|
Cba_Ntk_t * pBoxModel = Cba_ObjBoxModel( pNtk, iBox );
|
|
Vec_Int_t * vFanins = Cba_ObjFaninVec( pNtk, iBox );
|
|
int i, NameId;
|
|
Vec_IntForEachEntry( vMap, NameId, i )
|
|
assert( NameId == -1 );
|
|
// map formal names into I/O indexes
|
|
Cba_NtkForEachPi( pBoxModel, NameId, i )
|
|
{
|
|
assert( Vec_IntEntry(vMap, NameId) == -1 );
|
|
Vec_IntWriteEntry( vMap, NameId, i );
|
|
}
|
|
Cba_NtkForEachPo( pBoxModel, NameId, i )
|
|
{
|
|
assert( Vec_IntEntry(vMap, NameId) == -1 );
|
|
Vec_IntWriteEntry( vMap, NameId, Cba_NtkPiNum(pBoxModel) + i );
|
|
}
|
|
// remap box
|
|
assert( Vec_IntSize(vFanins) % 2 == 0 );
|
|
Vec_IntForEachEntry( vFanins, NameId, i )
|
|
{
|
|
assert( Vec_IntEntry(vMap, NameId) != -1 );
|
|
Vec_IntWriteEntry( vFanins, i++, Vec_IntEntry(vMap, NameId) );
|
|
}
|
|
// unmap formal inputs
|
|
Cba_NtkForEachPi( pBoxModel, NameId, i )
|
|
Vec_IntWriteEntry( vMap, NameId, -1 );
|
|
Cba_NtkForEachPo( pBoxModel, NameId, i )
|
|
Vec_IntWriteEntry( vMap, NameId, -1 );
|
|
}
|
|
void Cba_NtkRemapBoxes( Cba_Ntk_t * pNtk, Vec_Int_t * vMap )
|
|
{
|
|
int Type, iBox;
|
|
Cba_NtkForEachObjType( pNtk, Type, iBox )
|
|
if ( Type == CBA_OBJ_BOX )
|
|
Cba_BoxRemap( pNtk, iBox, vMap );
|
|
}
|
|
// create maps of NameId and boxes
|
|
int Cba_NtkCreateMap( Cba_Ntk_t * pNtk, Vec_Int_t * vMap, Vec_Int_t * vBoxes )
|
|
{
|
|
Vec_Int_t * vFanins;
|
|
int i, iObj, Type, Index, NameId;
|
|
int nObjCount = 0;
|
|
|
|
// map old name IDs into new object IDs
|
|
Vec_IntClear( vBoxes );
|
|
Cba_NtkForEachPi( pNtk, NameId, i )
|
|
{
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
printf( "Primary inputs %d and %d have the same name.\n", Vec_IntEntry(vMap, NameId), i );
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount++ );
|
|
}
|
|
Cba_NtkForEachObjType( pNtk, Type, iObj )
|
|
{
|
|
if ( Type == CBA_OBJ_NODE )
|
|
{
|
|
// consider node output name
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
NameId = Vec_IntEntry( vFanins, 0 );
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
printf( "Node output name %d is already driven.\n", NameId );
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount++ );
|
|
}
|
|
else if ( Type == CBA_OBJ_BOX )
|
|
{
|
|
Cba_Ntk_t * pNtkBox = Cba_ObjBoxModel( pNtk, iObj );
|
|
nObjCount += Cba_NtkPiNum(pNtkBox);
|
|
Vec_IntPush( vBoxes, nObjCount++ );
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
Vec_IntForEachEntry( vFanins, Index, i )
|
|
{
|
|
i++;
|
|
if ( Index < Cba_NtkPiNum(pNtkBox) )
|
|
continue;
|
|
assert( Index - Cba_NtkPiNum(pNtkBox) < Cba_NtkPoNum(pNtkBox) );
|
|
// consider box output name
|
|
NameId = Vec_IntEntry( vFanins, i );
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
printf( "Box output name %d is already driven.\n", NameId );
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount + Index - Cba_NtkPiNum(pNtkBox) );
|
|
}
|
|
nObjCount += Cba_NtkPoNum(pNtkBox);
|
|
}
|
|
}
|
|
// add outputs
|
|
nObjCount += Cba_NtkPoNum(pNtk);
|
|
return nObjCount;
|
|
}
|
|
void Cba_NtkCleanMap( Cba_Ntk_t * pNtk, Vec_Int_t * vMap )
|
|
{
|
|
Vec_Int_t * vFanins;
|
|
int i, iObj, Type, NameId;
|
|
Cba_NtkForEachPi( pNtk, NameId, i )
|
|
Vec_IntWriteEntry( vMap, NameId, -1 );
|
|
Cba_NtkForEachObjType( pNtk, Type, iObj )
|
|
{
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
if ( Type == CBA_OBJ_NODE )
|
|
{
|
|
Vec_IntForEachEntry( vFanins, NameId, i )
|
|
Vec_IntWriteEntry( vMap, NameId, -1 );
|
|
}
|
|
else if ( Type == CBA_OBJ_BOX )
|
|
{
|
|
Vec_IntForEachEntry( vFanins, NameId, i )
|
|
Vec_IntWriteEntry( vMap, Vec_IntEntry(vFanins, ++i), -1 );
|
|
}
|
|
}
|
|
Cba_NtkForEachPo( pNtk, NameId, i )
|
|
Vec_IntWriteEntry( vMap, NameId, -1 );
|
|
}
|
|
int Cba_NtkCheckNonDriven( Cba_Ntk_t * pNtk, Vec_Int_t * vMap, int nObjCount )
|
|
{
|
|
Vec_Int_t * vFanins;
|
|
int i, iObj, Type, NameId, Index;
|
|
int NonDriven = 0;
|
|
// check non-driven nets
|
|
Cba_NtkForEachObjType( pNtk, Type, iObj )
|
|
{
|
|
if ( Type == CBA_OBJ_NODE )
|
|
{
|
|
// consider node input names
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
Vec_IntForEachEntryStart( vFanins, NameId, i, 1 )
|
|
{
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
continue;
|
|
if ( NonDriven++ == 0 ) nObjCount++;
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount-1 );
|
|
}
|
|
}
|
|
else if ( Type == CBA_OBJ_BOX )
|
|
{
|
|
Cba_Ntk_t * pNtkBox = Cba_ObjBoxModel( pNtk, iObj );
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
Vec_IntForEachEntry( vFanins, Index, i )
|
|
{
|
|
i++;
|
|
if ( Index >= Cba_NtkPiNum(pNtkBox) )
|
|
continue;
|
|
// consider box input name
|
|
NameId = Vec_IntEntry( vFanins, i );
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
continue;
|
|
if ( NonDriven++ == 0 ) nObjCount++;
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount-1 );
|
|
}
|
|
}
|
|
}
|
|
Cba_NtkForEachPo( pNtk, NameId, i )
|
|
{
|
|
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
|
continue;
|
|
if ( NonDriven++ == 0 ) nObjCount++;
|
|
Vec_IntWriteEntry( vMap, NameId, nObjCount-1 );
|
|
}
|
|
if ( NonDriven > 0 )
|
|
printf( "Detected %d non-driven nets.\n", NonDriven );
|
|
return NonDriven;
|
|
}
|
|
Cba_Ntk_t * Cba_NtkBuild( Cba_Man_t * pNew, Cba_Ntk_t * pNtk, Vec_Int_t * vMap, Vec_Int_t * vBoxes, Vec_Int_t * vTemp, int nObjCount )
|
|
{
|
|
Vec_Int_t * vFanins;
|
|
Cba_Ntk_t * pNtkNew, * pNtkBox;
|
|
int i, iObj, ObjId, FaninId, Type, Index, NameId, nBoxes = 0;
|
|
|
|
// start network
|
|
pNtkNew = Cba_ManNtk( pNew, Cba_NtkId(pNtk) );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vTypes, nObjCount );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vFuncs, nObjCount );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vFanins, nObjCount );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vNameIds, nObjCount );
|
|
Cba_ManSetupArray( pNew, &pNtkNew->vBoxes, vBoxes );
|
|
|
|
// fill object information
|
|
Cba_NtkForEachPi( pNtk, NameId, i )
|
|
{
|
|
ObjId = Vec_IntEntry( vMap, NameId );
|
|
Vec_IntWriteEntry( &pNtkNew->vInputs, i, ObjId );
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, ObjId, CBA_OBJ_PI );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, ObjId, i );
|
|
Vec_IntWriteEntry( &pNtkNew->vNameIds, ObjId, NameId );
|
|
}
|
|
|
|
Cba_NtkForEachObjType( pNtk, Type, iObj )
|
|
{
|
|
vFanins = Cba_ObjFaninVec( pNtk, iObj );
|
|
if ( Type == CBA_OBJ_NODE )
|
|
{
|
|
ObjId = Vec_IntEntry( vMap, Vec_IntEntry(vFanins, 0) );
|
|
Vec_IntClear( vTemp );
|
|
Vec_IntForEachEntryStart( vFanins, NameId, i, 1 )
|
|
{
|
|
assert( Vec_IntEntry(vMap, NameId) != -1 );
|
|
Vec_IntPush( vTemp, Vec_IntEntry(vMap, NameId) );
|
|
}
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, ObjId, CBA_OBJ_NODE );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, ObjId, Cba_ObjFuncId(pNtk, iObj) );
|
|
Vec_IntWriteEntry( &pNtkNew->vFanins, ObjId, Cba_ManHandleArray(pNew, vTemp) );
|
|
Vec_IntWriteEntry( &pNtkNew->vNameIds, ObjId, Vec_IntEntry(vFanins, 0) );
|
|
}
|
|
else if ( Type == CBA_OBJ_BOX )
|
|
{
|
|
ObjId = Vec_IntEntry( &pNtkNew->vBoxes, nBoxes++ );
|
|
pNtkBox = Cba_ObjBoxModel( pNtk, iObj );
|
|
Cba_NtkSetHost( pNtkBox, Cba_NtkId(pNtk), ObjId );
|
|
// collect fanins
|
|
Vec_IntFill( vTemp, Cba_NtkPiNum(pNtkBox), -1 );
|
|
Vec_IntForEachEntry( vFanins, Index, i )
|
|
{
|
|
i++; NameId = Vec_IntEntry( vFanins, i );
|
|
assert( Vec_IntEntry(vMap, NameId) != -1 );
|
|
if ( Index < Cba_NtkPiNum(pNtkBox) )
|
|
{
|
|
Vec_IntWriteEntry( vTemp, Index, Vec_IntEntry(vMap, NameId) );
|
|
Vec_IntWriteEntry( &pNtkNew->vNameIds, ObjId - Cba_NtkPiNum(pNtkBox) + Index, NameId );
|
|
}
|
|
else
|
|
{
|
|
assert( Vec_IntEntry(vMap, NameId) == ObjId + 1 + Index - Cba_NtkPiNum(pNtkBox) );
|
|
Vec_IntWriteEntry( &pNtkNew->vNameIds, Vec_IntEntry(vMap, NameId), NameId );
|
|
}
|
|
}
|
|
Vec_IntForEachEntry( vTemp, Index, i )
|
|
assert( Index >= 0 );
|
|
// create box
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, ObjId, CBA_OBJ_BOX );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, ObjId, Cba_ManNtkId(pNew, Cba_NtkName(pNtkBox)) );
|
|
// create box inputs
|
|
Cba_BoxForEachBi( pNtkNew, ObjId, FaninId, i )
|
|
{
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, FaninId, CBA_OBJ_BI );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, FaninId, i );
|
|
Vec_IntWriteEntry( &pNtkNew->vFanins, FaninId, Cba_ManHandleBuffer(pNew, Vec_IntEntry(vTemp, i)) );
|
|
}
|
|
// create box outputs
|
|
Cba_BoxForEachBo( pNtkNew, ObjId, FaninId, i )
|
|
{
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, FaninId, CBA_OBJ_BO );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, FaninId, i );
|
|
Vec_IntWriteEntry( &pNtkNew->vFanins, FaninId, Cba_ManHandleBuffer(pNew, ObjId) );
|
|
}
|
|
}
|
|
}
|
|
assert( nBoxes == Vec_IntSize(&pNtkNew->vBoxes) );
|
|
Cba_NtkForEachPo( pNtk, NameId, i )
|
|
{
|
|
ObjId = nObjCount - Cba_NtkPoNum(pNtk) + i;
|
|
FaninId = Vec_IntEntry( vMap, NameId );
|
|
assert( FaninId != -1 );
|
|
Vec_IntWriteEntry( &pNtkNew->vOutputs, i, ObjId );
|
|
Vec_IntWriteEntry( &pNtkNew->vTypes, ObjId, CBA_OBJ_PO );
|
|
Vec_IntWriteEntry( &pNtkNew->vFuncs, ObjId, i );
|
|
Vec_IntWriteEntry( &pNtkNew->vFanins, ObjId, Cba_ManHandleBuffer(pNew, FaninId) );
|
|
// remove NameId from the driver and assign it to the output
|
|
//Vec_IntWriteEntry( &pNtkNew->vNameIds, FaninId, -1 );
|
|
Vec_IntWriteEntry( &pNtkNew->vNameIds, ObjId, NameId );
|
|
}
|
|
return pNtkNew;
|
|
}
|
|
Cba_Man_t * Cba_ManPreBuild( Cba_Man_t * p )
|
|
{
|
|
Cba_Man_t * pNew = Cba_ManClone( p );
|
|
Cba_Ntk_t * pNtk, * pNtkNew; int i;
|
|
Cba_ManForEachNtk( p, pNtk, i )
|
|
{
|
|
pNtkNew = Cba_NtkAlloc( pNew, Cba_NtkName(pNtk) );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vInputs, Cba_NtkPiNum(pNtk) );
|
|
Cba_ManFetchArray( pNew, &pNtkNew->vOutputs, Cba_NtkPoNum(pNtk) );
|
|
}
|
|
assert( Cba_ManNtkNum(pNew) == Cba_ManNtkNum(p) );
|
|
return pNew;
|
|
}
|
|
Cba_Man_t * Cba_ManBuild( Cba_Man_t * p )
|
|
{
|
|
Cba_Man_t * pNew = Cba_ManPreBuild( p );
|
|
Vec_Int_t * vMap = Vec_IntStartFull( Abc_NamObjNumMax(p->pNames) + 1 );
|
|
Vec_Int_t * vBoxes = Vec_IntAlloc( 1000 );
|
|
Vec_Int_t * vTemp = Vec_IntAlloc( 1000 );
|
|
Cba_Ntk_t * pNtk; int i, nObjs;
|
|
assert( Abc_NamObjNumMax(p->pModels) == Cba_ManNtkNum(p) + 1 );
|
|
Cba_ManForEachNtk( p, pNtk, i )
|
|
{
|
|
Cba_NtkRemapBoxes( pNtk, vMap );
|
|
nObjs = Cba_NtkCreateMap( pNtk, vMap, vBoxes );
|
|
Cba_NtkCheckNonDriven( pNtk, vMap, nObjs );
|
|
Cba_NtkBuild( pNew, pNtk, vMap, vBoxes, vTemp, nObjs );
|
|
Cba_NtkCleanMap( pNtk, vMap );
|
|
}
|
|
Vec_IntFree( vTemp );
|
|
Vec_IntFree( vBoxes );
|
|
Vec_IntFree( vMap );
|
|
return pNew;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|