summaryrefslogtreecommitdiffstats
path: root/src/base/abc/abcUtil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/abc/abcUtil.c')
-rw-r--r--src/base/abc/abcUtil.c170
1 files changed, 112 insertions, 58 deletions
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c
index 2dbfef33..6e506b0e 100644
--- a/src/base/abc/abcUtil.c
+++ b/src/base/abc/abcUtil.c
@@ -444,12 +444,10 @@ void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeHasCoFanout( Abc_Obj_t * pNode )
+Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout;
int i;
- if ( !Abc_ObjIsNode(pNode) )
- return NULL;
Abc_ObjForEachFanout( pNode, pFanout, i )
if ( Abc_ObjIsCo(pFanout) )
return pFanout;
@@ -458,9 +456,30 @@ Abc_Obj_t * Abc_NodeHasCoFanout( Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Checks if the internal node has CO fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( !Abc_ObjIsCo(pFanout) )
+ return pFanout;
+ return NULL;
+}
+
+/**Function*************************************************************
+
Synopsis [Checks if the internal node has CO drivers with the same name.]
- Description [Checks if the internal node can borrow a name from CO fanouts.
+ Description [Checks if the internal node can borrow its name from CO fanouts.
This is possible if all COs with non-complemented fanin edge pointing to this
node have the same name.]
@@ -473,8 +492,6 @@ Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout, * pFanoutCo;
int i;
- if ( !Abc_ObjIsNode(pNode) )
- return NULL;
pFanoutCo = NULL;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
@@ -497,13 +514,60 @@ Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Fixes the CO driver problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate )
+{
+ Abc_Ntk_t * pNtk = pDriver->pNtk;
+ Abc_Obj_t * pDriverNew, * pFanin;
+ int k;
+ if ( fDuplicate && !Abc_ObjIsCi(pDriver) )
+ {
+ pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 );
+ Abc_ObjForEachFanin( pDriver, pFanin, k )
+ Abc_ObjAddFanin( pDriverNew, pFanin );
+ if ( Abc_ObjFaninC0(pNodeCo) )
+ {
+ // change polarity of the duplicated driver
+ Abc_NodeComplement( pDriverNew );
+ Abc_ObjXorFaninC( pNodeCo, 0 );
+ }
+ }
+ else
+ {
+ // add inverters and buffers when necessary
+ if ( Abc_ObjFaninC0(pNodeCo) )
+ {
+ pDriverNew = Abc_NodeCreateInv( pNtk, pDriver );
+ Abc_ObjXorFaninC( pNodeCo, 0 );
+ }
+ else
+ pDriverNew = Abc_NodeCreateBuf( pNtk, pDriver );
+ }
+ // update the fanin of the PO node
+ Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew );
+ assert( Abc_ObjFanoutNum(pDriverNew) == 1 );
+ // remove the old driver if it dangles
+ // (this happens when the duplicated driver had only one complemented fanout)
+ if ( Abc_ObjFanoutNum(pDriver) == 0 )
+ Abc_NtkDeleteObj( pDriver );
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if COs of a logic network are simple.]
Description [The COs of a logic network are simple under three conditions:
(1) The edge from CO to its driver is not complemented.
- (2) No two COs share the same driver.
- (3) The driver is not a CI unless the CI and the CO have the same name
- (and so the inv/buf should not be written into a file).]
+ (2) If CI is a driver of a CO, they have the same name.]
+ (2) If two COs share the same driver, they have the same name.]
SideEffects []
@@ -514,19 +578,27 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode, * pDriver;
int i;
- assert( !Abc_NtkIsNetlist(pNtk) );
- // check if there are complemented or idential POs
+ assert( Abc_NtkIsLogic(pNtk) );
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
+ // if the driver is complemented, this is an error
pDriver = Abc_ObjFanin0(pNode);
if ( Abc_ObjFaninC0(pNode) )
return 0;
- if ( Abc_NodeIsTravIdCurrent(pDriver) )
+ // if the driver is a CI and has different name, this is an error
+ if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
return 0;
- if ( Abc_ObjIsCi(pDriver) && strcmp( Abc_ObjName(pDriver), Abc_ObjName(pNode) ) != 0 )
+ // if the driver is visited for the first time, remember the CO name
+ if ( !Abc_NodeIsTravIdCurrent(pDriver) )
+ {
+ pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+ Abc_NodeSetTravIdCurrent(pDriver);
+ continue;
+ }
+ // the driver has second CO - if they have different name, this is an error
+ if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
return 0;
- Abc_NodeSetTravIdCurrent(pDriver);
}
return 1;
}
@@ -536,10 +608,9 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
Synopsis [Transforms the network to have simple COs.]
Description [The COs of a logic network are simple under three conditions:
- (1) The edge from the CO to its driver is not complemented.
- (2) No two COs share the same driver (unless they have the same name!).
- (3) The driver is not a CI unless the CI and the CO have the same name
- (and so the inv/buf should not be written into a file).
+ (1) The edge from CO to its driver is not complemented.
+ (2) If CI is a driver of a CO, they have the same name.]
+ (2) If two COs share the same driver, they have the same name.
In some cases, such as FPGA mapping, we prevent the increase in delay
by duplicating the driver nodes, rather than adding invs/bufs.]
@@ -550,58 +621,41 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
***********************************************************************/
int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate )
{
- Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin;
- int i, k, nDupGates = 0;
+ Abc_Obj_t * pNode, * pDriver;
+ int i, nDupGates = 0;
assert( Abc_NtkIsLogic(pNtk) );
- // process the COs by adding inverters and buffers when necessary
+ Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
+ // if the driver is complemented, this is an error
pDriver = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pDriver) )
+ if ( Abc_ObjFaninC0(pNode) )
{
- // skip the case when the driver is a different node with the same name
- if ( pDriver != pNode && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) == 0 )
- {
- assert( !Abc_ObjFaninC0(pNode) );
- continue;
- }
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- else if ( !Abc_ObjFaninC0(pNode) )
+ // if the driver is a CI and has different name, this is an error
+ if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
{
- // skip the case when all CO fanouts of the driver have the same name
- if ( Abc_NodeHasUniqueCoFanout(pDriver) )
- continue;
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- if ( fDuplicate && !Abc_ObjIsCi(pDriver) )
+ // if the driver is visited for the first time, remember the CO name
+ if ( !Abc_NodeIsTravIdCurrent(pDriver) )
{
- pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 );
- Abc_ObjForEachFanin( pDriver, pFanin, k )
- Abc_ObjAddFanin( pDriverNew, pFanin );
- if ( Abc_ObjFaninC0(pNode) )
- {
- // change polarity of the duplicated driver
- Abc_NodeComplement( pDriverNew );
- Abc_ObjXorFaninC( pNode, 0 );
- }
+ pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+ Abc_NodeSetTravIdCurrent(pDriver);
+ continue;
}
- else
+ // the driver has second CO - if they have different name, this is an error
+ if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
{
- // add inverters and buffers when necessary
- if ( Abc_ObjFaninC0(pNode) )
- {
- pDriverNew = Abc_NodeCreateInv( pNtk, pDriver );
- Abc_ObjXorFaninC( pNode, 0 );
- }
- else
- pDriverNew = Abc_NodeCreateBuf( pNtk, pDriver );
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- // update the fanin of the PO node
- Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
- assert( Abc_ObjFanoutNum(pDriverNew) == 1 );
- nDupGates++;
- // remove the old driver if it dangles
- if ( Abc_ObjFanoutNum(pDriver) == 0 )
- Abc_NtkDeleteObj( pDriver );
}
assert( Abc_NtkLogicHasSimpleCos(pNtk) );
return nDupGates;