/**CFile***********************************************************************
FileName [grabUtil.c]
PackageName [grab]
Synopsis [The utility functions for abstraction refinement.]
Description [This file contains the functions to check invariant
properties by the GRAB abstraction refinement algorithm. GRAB stands
for "Generational Refinement of Ariadne's Bundle," in which the
automatic refinement is guided by all shortest abstract
counter-examples. For more information, please check the ICCAD'03
paper of Wang et al., "Improving Ariadne's Bundle by Following
Multiple Counter-Examples in Abstraction Refinement." ]
Author [Chao Wang]
Copyright [Copyright (c) 2004 The Regents of the Univ. of Colorado.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in
all copies of this software.]
******************************************************************************/
#include "grabInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Structure declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static void GetFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *F, array_t *formulaNodes);
static void GetFaninLatches(Ntk_Node_t *node, st_table *visited, st_table *absVarTable);
static void NodeTableAddCtlFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *formula, st_table * nodesTable);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Compute the Cone-Of-Influence abstract model.]
Description [Compute the Cone-Of-Influence abstraction, which
consists of latches in the transitive supprot of the property.]
SideEffects []
******************************************************************************/
st_table *
GrabComputeCOIAbstraction(
Ntk_Network_t *network,
Ctlp_Formula_t *invFormula)
{
st_table *formulaNodes;
array_t *formulaCombNodes;
Ntk_Node_t *node;
array_t *nodeArray;
int i;
st_generator *stGen;
st_table *absVarTable;
/* find network nodes in the immediate support of the property */
formulaNodes = st_init_table(st_ptrcmp, st_ptrhash);
NodeTableAddCtlFormulaNodes(network, invFormula, formulaNodes);
/* find network nodes in the transitive fan-in */
nodeArray = array_alloc(Ntk_Node_t *, 0);
st_foreach_item(formulaNodes, stGen, & node, NIL(char *)) {
array_insert_last( Ntk_Node_t *, nodeArray, node);
}
st_free_table(formulaNodes);
formulaCombNodes = Ntk_NodeComputeTransitiveFaninNodes(network, nodeArray,
FALSE, TRUE);
array_free(nodeArray);
/* extract all the latches */
absVarTable = st_init_table(st_ptrcmp, st_ptrhash);
arrayForEachItem(Ntk_Node_t *, formulaCombNodes, i, node) {
if (Ntk_NodeTestIsLatch(node) == TRUE) {
st_insert(absVarTable, node, (char *)0);
}
}
array_free(formulaCombNodes);
return absVarTable;
}
/**Function********************************************************************
Synopsis [Compute the initial abstract model.]
Description [Compute the he initial abstraction, which consists of
latches in the immediate supprot of the property.]
SideEffects []
******************************************************************************/
st_table *
GrabComputeInitialAbstraction(
Ntk_Network_t *network,
Ctlp_Formula_t *invFormula)
{
array_t *formulaNodes = array_alloc(Ntk_Node_t *, 0);
Ntk_Node_t *node;
int i;
st_table *absVarTable, *visited;
GetFormulaNodes(network, invFormula, formulaNodes);
absVarTable = st_init_table(st_ptrcmp, st_ptrhash);
visited = st_init_table(st_ptrcmp, st_ptrhash);
arrayForEachItem(Ntk_Node_t *, formulaNodes, i, node) {
GetFaninLatches(node, visited, absVarTable);
}
st_free_table(visited);
array_free(formulaNodes);
return absVarTable;
}
/**Function********************************************************************
Synopsis [Build or update partition for the current abstract model.]
Description [Build or update partition for the current abstract
model. It is a two-phase process, in which the first phase generated
the Bnvs---intermediate variables that should be created; while the
second phase actually create the BDDs.
When a non-empty hash table 'absBnvTable' is given, BNVs not in this
table should be treated as inputs---they should not appear in the
partition either.
When 'absBnvTable' is not provided (e.g. when fine-grain abstraction
is disabled), all relevant BNVs should appear in the partition.]
SideEffects []
******************************************************************************/
void
GrabUpdateAbstractPartition(
Ntk_Network_t *network,
st_table *coiBnvTable,
st_table *absVarTable,
st_table *absBnvTable,
int partitionFlag)
{
graph_t *newPart;
st_table *useAbsBnvTable = absBnvTable? absBnvTable:coiBnvTable;
if (partitionFlag == GRAB_PARTITION_BUILD) {
/* free the existing partition */
Ntk_NetworkFreeApplInfo(network, PART_NETWORK_APPL_KEY);
/* insert bnvs whenever necessary. Note that when the current
* partition is not available, this function will create new bnvs
* and put them into the coiBnvTable. Otherwise, it retrieves
* existing bnvs from the current partiton */
Part_PartitionReadOrCreateBnvs(network, absVarTable, coiBnvTable);
/* create the new partition */
newPart = g_alloc();
newPart->user_data = (gGeneric)PartPartitionInfoCreate("default",
Ntk_NetworkReadMddManager(network),
Part_Frontier_c);
Part_PartitionWithExistingBnvs(network, newPart, coiBnvTable,
absVarTable, useAbsBnvTable);
Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
(Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
(void *) newPart);
}else if (partitionFlag == GRAB_PARTITION_UPDATE) {
fprintf(vis_stdout,
"\n ** grab error: GRAB_PARTITION_UPDATE not implemented\n");
assert(0);
}
}
/**Function********************************************************************
Synopsis [Create the abstract FSM.]
Description [Create the abstract FSM. Table 'coiBnvTable' contains
all the BNVs (i.e. intermediate variables), while Table
'absBnvTable' contains all the visible BNVs. BNVs not in absBnvTable
should be treated as inputs.
When absBnvTable is NULL (e.g. fine-grain abstraction is disabled),
no BNV is treated as input.
If independentFlag is TRUE, invisible latches are regarded as
inputs; otherwise, they are regarded as latches.]
SideEffects []
******************************************************************************/
Fsm_Fsm_t *
GrabCreateAbstractFsm(
Ntk_Network_t *network,
st_table *coiBnvTable,
st_table *absVarTable,
st_table *absBnvTable,
int partitionFlag,
int independentFlag)
{
Fsm_Fsm_t *fsm;
array_t *absLatches = array_alloc(Ntk_Node_t *, 0);
array_t *invisibleVars = array_alloc(Ntk_Node_t *, 0);
array_t *absInputs = array_alloc(Ntk_Node_t *, 0);
array_t *rootNodesArray = array_alloc(Ntk_Node_t *, 0);
st_table *rawLeafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
lsList topologicalNodeList;
lsGen lsgen;
st_generator *stgen;
Ntk_Node_t *node;
GrabUpdateAbstractPartition(network, coiBnvTable, absVarTable, absBnvTable,
partitionFlag);
/* first, compute the absLatches, invisibleVars, and absInputs:
* absLatches includes all the visible latch variables;
* invisibleVars includes all the invisible latches variables;
* absInputs includes all the primary and pseudo inputs.
*/
st_foreach_item(absVarTable, stgen, &node, NIL(char *)) {
array_insert_last(Ntk_Node_t *, absLatches, node);
array_insert_last(Ntk_Node_t *, rootNodesArray,
Ntk_LatchReadDataInput(node));
array_insert_last(Ntk_Node_t *, rootNodesArray,
Ntk_LatchReadInitialInput(node));
}
Ntk_NetworkForEachCombInput(network, lsgen, node) {
st_insert(rawLeafNodesTable, node, (char *) (long) (-1) );
}
st_foreach_item(coiBnvTable, stgen, &node, NIL(char *)) {
/* unless it blongs to the current Abstract Model */
if (absBnvTable && !st_is_member(absBnvTable, node))
st_insert(rawLeafNodesTable, node, (char *) (long) (-1) );
}
topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
rootNodesArray,
rawLeafNodesTable);
lsForEachItem(topologicalNodeList, lsgen, node){
if (st_is_member(rawLeafNodesTable, node) &&
!st_is_member(absVarTable, node) ) {
/*if (Ntk_NodeTestIsLatch(node) ||
coiBnvTable && st_is_member(coiBnvTable, node))*/
if (Ntk_NodeTestIsLatch(node) ||
(coiBnvTable && st_is_member(coiBnvTable, node)))
array_insert_last(Ntk_Node_t *, invisibleVars, node);
else
array_insert_last(Ntk_Node_t *, absInputs, node);
}
}
lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
st_free_table(rawLeafNodesTable);
array_free(rootNodesArray);
/* now, create the abstract Fsm according to the value of
* independentFlag when independentFlag is TRUE, the present state
* varaibles are absLatches; otherwise, they contain both absLatches
* and invisibleVars (with such a FSM, preimages may contain
* invisible vars in their supports)
*/
fsm = Fsm_FsmCreateAbstractFsm(network, NIL(graph_t),
absLatches, invisibleVars, absInputs,
NIL(array_t), independentFlag);
#if 0
/* for debugging */
if (partitionFlag == GRAB_PARTITION_NOCHANGE) {
GrabPrintNodeArray("absLatches", absLatches);
GrabPrintNodeArray("invisibleVars", invisibleVars);
GrabPrintNodeArray("absInputs", absInputs);
}
#endif
array_free(invisibleVars);
array_free(absInputs);
array_free(absLatches);
return fsm;
}
/**Function********************************************************************
Synopsis [Computes the set of initial states of set of latches.]
Description [Computes the set of initial states of a set of latches.
The nodes driving the initial inputs of the latches, called the
initial nodes, must not have latches in their support. If an
initial node is found that has a latch in its transitive fanin, then
a NULL MDD is returned, and a message is written to the
error_string.
The initial states are computed as follows. For each latch i, the relation
(x_i = g_i(u)) is built, where x_i is the present state variable of latch i,
and g_i(u) is the multi-valued initialization function of latch i, in terms
of the input variables u. These relations are then conjuncted, and the
input variables are existentially quantified from the result
(i.e. init_states(x) = \exists u \[\prod (x_i = g_i(u))\]).]
SideEffects [The result of the initial state computation is stored with
the FSM.]
SeeAlso [Fsm_FsmComputeReachableStates]
******************************************************************************/
mdd_t *
GrabComputeInitialStates(
Ntk_Network_t *network,
array_t *psVars)
{
int i = 0;
mdd_t *initStates;
Ntk_Node_t *node;
array_t *initRelnArray;
array_t *initMvfs;
array_t *initNodes;
array_t *initVertices;
array_t *latchMddIds;
array_t *inputVars = array_alloc(int, 0);
array_t *combArray;
st_table *supportNodes;
st_table *supportVertices;
mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
graph_t *partition =
(graph_t *) Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY);
int numLatches;
Img_MethodType imageMethod;
numLatches = array_n(psVars);
/* Get the array of initial nodes, both as network nodes and as
* partition vertices.
*/
initNodes = array_alloc(Ntk_Node_t *, numLatches);
initVertices = array_alloc(vertex_t *, numLatches);
latchMddIds = array_alloc(int, numLatches);
for (i=0; i=0; j--) {
mdd1 = array_fetch(mdd_t *, synOnionRings, j+1);
mdd2 = Img_ImageInfoComputeBwdWithDomainVars(imageInfo,
mdd1,
mdd1,
mddOne);
mdd3 = array_fetch(mdd_t *, onionRings, j);
mdd4 = mdd_and(mdd2, mdd3, 1, 1);
mdd_free(mdd2);
if (cexType == GRAB_CEX_MINTERM)
ring = Mc_ComputeAMinterm(mdd4, allPSVars, mddManager);
else if (cexType == GRAB_CEX_CUBE) {
array_t *bddIds = mdd_get_bdd_support_ids(mddManager, mdd4);
int nvars = array_n(bddIds);
array_free(bddIds);
ring = bdd_approx_remap_ua(mdd4, (bdd_approx_dir_t)BDD_UNDER_APPROX,
nvars, 1024, 1);
if (ring == NIL(mdd_t))
ring = mdd_dup(mdd4);
}else
ring = mdd_dup(mdd4);
mdd_free(mdd4);
array_insert(mdd_t *, synOnionRings, j, ring);
}
mdd_free(mddOne);
return synOnionRings;
}
/**Function********************************************************************
Synopsis [Get the visible variable mddIds of the current abstraction.]
Description [Get the visible variable mddIds of the current
abstraction. Note that they are the state variables.]
SideEffects []
******************************************************************************/
array_t *
GrabGetVisibleVarMddIds (
Fsm_Fsm_t *absFsm,
st_table *absVarTable)
{
array_t *visibleVarMddIds = array_alloc(int, 0);
st_generator *stgen;
Ntk_Node_t *node;
int mddId;
st_foreach_item(absVarTable, stgen, &node, NIL(char *)) {
mddId = Ntk_NodeReadMddId(node);
array_insert_last(int, visibleVarMddIds, mddId);
}
return visibleVarMddIds;
}
/**Function********************************************************************
Synopsis [Get the invisible variable mddIds of the current abstraction.]
Description [Get the invisible variable mddIds of the current
abstraction. Note that they include both state variables and boolean
network variables.]
SideEffects []
******************************************************************************/
array_t *
GrabGetInvisibleVarMddIds(
Fsm_Fsm_t *absFsm,
st_table *absVarTable,
st_table *absBnvTable)
{
Ntk_Network_t *network = Fsm_FsmReadNetwork(absFsm);
array_t *inputVars = Fsm_FsmReadInputVars(absFsm);
array_t *invisibleVarMddIds = array_alloc(int, 0);
Ntk_Node_t *node;
int i, mddId;
arrayForEachItem(int, inputVars, i, mddId) {
node = Ntk_NetworkFindNodeByMddId(network, mddId);
if ( !Ntk_NodeTestIsInput(node) &&
!st_is_member(absVarTable, node) ) {
if (absBnvTable != NIL(st_table)) {
if (!st_is_member(absBnvTable, node)) {
array_insert_last(int, invisibleVarMddIds, mddId);
}
}else
array_insert_last(int, invisibleVarMddIds, mddId);
}
}
return invisibleVarMddIds;
}
/**Function********************************************************************
Synopsis [Test whether the refinement set of latches is sufficient.]
Description [Test whether the refinement set of latches is sufficient.]
SideEffects []
******************************************************************************/
int
GrabTestRefinementSetSufficient(
Ntk_Network_t *network,
array_t *SORs,
st_table *absVarTable,
int verbose)
{
int is_sufficient;
is_sufficient = !Bmc_AbstractCheckAbstractTraces(network,
SORs,
absVarTable,
0, 0, 0);
return is_sufficient;
}
/**Function********************************************************************
Synopsis [Test whether the refinement set of BNVs is sufficient.]
Description [Test whether the refinement set of BNVs is sufficient.]
SideEffects []
******************************************************************************/
int
GrabTestRefinementBnvSetSufficient(
Ntk_Network_t *network,
st_table *coiBnvTable,
array_t *SORs,
st_table *absVarTable,
st_table *absBnvTable,
int verbose)
{
int is_sufficient;
assert(absBnvTable && coiBnvTable);
is_sufficient =
!Bmc_AbstractCheckAbstractTracesWithFineGrain(network,
coiBnvTable,
SORs,
absVarTable,
absBnvTable);
return is_sufficient;
}
/**Function********************************************************************
Synopsis [Minimize the refinement set of latch variable.]
Description [Minimize the refinement set of latch variable. After
that, also prune away the boolean network variables that are no
longer in the transitive fan-in.]
SideEffects []
******************************************************************************/
void
GrabMinimizeLatchRefinementSet(
Ntk_Network_t *network,
st_table **absVarTable,
st_table **absBnvTable,
array_t *newlyAddedLatches,
array_t **newlyAddedBnvs,
array_t *SORs,
int verbose)
{
st_table *newVertexTable, *oldBnvTable, *transFaninTable;
array_t *rootArray, *transFanins, *oldNewlyAddedBnvs;
st_generator *stgen;
Ntk_Node_t *node;
int i, flag, n_size, mddId;
n_size = array_n(newlyAddedLatches);
if (verbose >= 3)
fprintf(vis_stdout,
"-- grab: minimize latch refinement set: previous size is %d\n",
n_size);
arrayForEachItem(int, newlyAddedLatches, i, mddId) {
node = Ntk_NetworkFindNodeByMddId(network, mddId);
/* first, try to drop it */
newVertexTable = st_copy(*absVarTable);
flag = st_delete(newVertexTable, &node, NIL(char *));
assert(flag);
/* if the counter-example does not come back, drop it officially */
flag = Bmc_AbstractCheckAbstractTraces(network,SORs,
newVertexTable, 0, 0, 0);
if (!flag) {
st_free_table(*absVarTable);
*absVarTable = newVertexTable;
n_size--;
}else {
st_free_table(newVertexTable);
if (verbose >= 3)
fprintf(vis_stdout," add back %s (latch)\n",
Ntk_NodeReadName(node));
}
}
if (verbose >= 3)
fprintf(vis_stdout,
"-- grab: minimize latch refinement set: current size is %d\n",
n_size);
/* prune away irrelevant BNVs */
if (*absBnvTable != NIL(st_table) && st_count(*absBnvTable)>0) {
rootArray = array_alloc(Ntk_Node_t *, 0);
st_foreach_item(*absVarTable, stgen, &node, NIL(char *)) {
array_insert_last(Ntk_Node_t *, rootArray, Ntk_LatchReadDataInput(node));
array_insert_last(Ntk_Node_t *, rootArray,
Ntk_LatchReadInitialInput(node));
}
transFanins = Ntk_NodeComputeTransitiveFaninNodes(network, rootArray,
TRUE, /*stopAtLatch*/
FALSE /*combInputsOnly*/
);
array_free(rootArray);
transFaninTable = st_init_table(st_ptrcmp, st_ptrhash);
arrayForEachItem(Ntk_Node_t *, transFanins, i, node) {
st_insert(transFaninTable, node, NIL(char));
}
array_free(transFanins);
oldBnvTable = *absBnvTable;
oldNewlyAddedBnvs = *newlyAddedBnvs;
*absBnvTable = st_init_table(st_ptrcmp, st_ptrhash);
*newlyAddedBnvs = array_alloc(int, 0);
st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) {
if (st_is_member(transFaninTable, node))
st_insert(*absBnvTable, node, NIL(char));
}
arrayForEachItem(int, oldNewlyAddedBnvs, i, mddId) {
node = Ntk_NetworkFindNodeByMddId(network, mddId);
if (st_is_member(transFaninTable, node))
array_insert_last(int, *newlyAddedBnvs, mddId);
}
st_free_table(transFaninTable);
if (verbose >= 5) {
st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) {
if (!st_is_member(*absBnvTable, node))
fprintf(vis_stdout, " prune away BNV %s\n", Ntk_NodeReadName(node));
}
}
array_free(oldNewlyAddedBnvs);
st_free_table(oldBnvTable);
}
}
/**Function********************************************************************
Synopsis [Minimize the refinement set of latch variable.]
Description [Minimize the refinement set of latch variable. After
that, also prune away the boolean network variables that are no
longer in the transitive fan-in.]
SideEffects []
******************************************************************************/
void
GrabMinimizeBnvRefinementSet(
Ntk_Network_t *network,
st_table *coiBnvTable,
st_table *absVarTable,
st_table **absBnvTable,
array_t *newlyAddedBnvs,
array_t *SORs,
int verbose)
{
st_table *newBnvTable;
Ntk_Node_t *node;
int i, flag, n_size, mddId;
n_size = array_n(newlyAddedBnvs);
if (verbose >= 3)
fprintf(vis_stdout,
"-- grab: minimize bnv refinement set: previous size is %d\n",
n_size);
arrayForEachItem(int, newlyAddedBnvs, i, mddId) {
node = Ntk_NetworkFindNodeByMddId(network, mddId);
/* first, try to drop it */
newBnvTable = st_copy(*absBnvTable);
flag = st_delete(newBnvTable, &node, NIL(char *));
assert(flag);
/* if the counter-example does not come back, drop it officially */
flag = Bmc_AbstractCheckAbstractTracesWithFineGrain(network,
coiBnvTable,
SORs,
absVarTable,
newBnvTable);
if (!flag) {
st_free_table(*absBnvTable);
*absBnvTable = newBnvTable;
n_size--;
}else {
st_free_table(newBnvTable);
if (verbose >= 3)
fprintf(vis_stdout," add back %s (BNV)\n",
Ntk_NodeReadName(node));
}
}
if (verbose >= 3)
fprintf(vis_stdout,
"-- grab: minimize bnv refinement set: current size is %d\n",
n_size);
}
/**Function********************************************************************
Synopsis [Clear the fields of mddId for all network nodes.]
Description [Clear the fields of mddId for all network nodes.]
SideEffects []
******************************************************************************/
void
GrabNtkClearAllMddIds(
Ntk_Network_t *network)
{
#ifndef NDEBUG
mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
#endif
Ntk_Node_t *node;
lsGen lsgen;
assert(mddManager == NIL(mdd_manager));
Ntk_NetworkForEachNode(network, lsgen, node) {
Ntk_NodeSetMddId(node, NTK_UNASSIGNED_MDD_ID);
}
}
/**Function********************************************************************
Synopsis [Print an array of network nodes.]
Description [Print an array of network nodes.]
SideEffects []
******************************************************************************/
void
GrabPrintNodeArray(
char *caption,
array_t *theArray)
{
Ntk_Node_t *node;
char string[32];
int i;
fprintf(vis_stdout, "\n%s[%d] =\n", caption, theArray?array_n(theArray):0);
if (!theArray) return;
arrayForEachItem(Ntk_Node_t *, theArray, i, node) {
if (Ntk_NodeTestIsLatch(node))
strcpy(string, "latch");
else if (Ntk_NodeTestIsInput(node))
strcpy(string, "input");
else if (Ntk_NodeTestIsLatchDataInput(node))
strcpy(string, "latchDataIn");
else if (Ntk_NodeTestIsLatchInitialInput(node))
strcpy(string, "latchInitIn");
else if (Ntk_NodeTestIsConstant(node))
strcpy(string, "const");
else
strcpy(string, "BNV");
fprintf(vis_stdout, "%s\t(%s)\n", Ntk_NodeReadName(node), string);
}
}
/**Function********************************************************************
Synopsis [Print an array of network nodes.]
Description [Print an array of network nodes.]
SideEffects []
******************************************************************************/
void
GrabPrintMddIdArray(
Ntk_Network_t *network,
char *caption,
array_t *mddIdArray)
{
Ntk_Node_t *node;
array_t *theArray = array_alloc(Ntk_Node_t *, array_n(mddIdArray));
int i, mddId;
arrayForEachItem(int, mddIdArray, i, mddId) {
node = Ntk_NetworkFindNodeByMddId(network, mddId);
array_insert(Ntk_Node_t *, theArray, i, node);
}
GrabPrintNodeArray(caption, theArray);
array_free(theArray);
}
/**Function********************************************************************
Synopsis [Print a list of network nodes.]
Description [Print a list of network nodes.]
SideEffects []
******************************************************************************/
void
GrabPrintNodeList(
char *caption,
lsList theList)
{
Ntk_Node_t *node;
char string[32];
lsGen lsgen;
fprintf(vis_stdout, "\n%s[%d] =\n", caption, theList?lsLength(theList):0);
if (!theList) return;
lsForEachItem(theList, lsgen, node) {
if (Ntk_NodeTestIsLatch(node))
strcpy(string, "latch");
else if (Ntk_NodeTestIsInput(node))
strcpy(string, "input");
else if (Ntk_NodeTestIsLatchDataInput(node))
strcpy(string, "latchDataIn");
else if (Ntk_NodeTestIsLatchInitialInput(node))
strcpy(string, "latchInitIn");
else if (Ntk_NodeTestIsConstant(node))
strcpy(string, "const");
else
strcpy(string, "BNV");
fprintf(vis_stdout, " %s\t %s\n", string, Ntk_NodeReadName(node));
}
}
/**Function********************************************************************
Synopsis [Print a hash table of network nodes.]
Description [Print a hash table of network nodes.]
SideEffects []
******************************************************************************/
void
GrabPrintNodeHashTable(
char *caption,
st_table *theTable)
{
Ntk_Node_t *node;
char string[32];
long value;
st_generator *stgen;
fprintf(vis_stdout, "\n%s[%d] =\n", caption, theTable?st_count(theTable):0);
if (!theTable) return;
st_foreach_item(theTable, stgen, &node, &value) {
if (Ntk_NodeTestIsLatch(node))
strcpy(string, "latch");
else if (Ntk_NodeTestIsInput(node))
strcpy(string, "input");
else if (Ntk_NodeTestIsLatchDataInput(node))
strcpy(string, "latchDataIn");
else if (Ntk_NodeTestIsLatchInitialInput(node))
strcpy(string, "latchInitIn");
else if (Ntk_NodeTestIsConstant(node))
strcpy(string, "const");
else
strcpy(string, "BNV");
if (value != 0)
fprintf(vis_stdout, " %s\t %s\t %ld\n", string, Ntk_NodeReadName(node),
value);
else
fprintf(vis_stdout, " %s\t %s \n", string, Ntk_NodeReadName(node));
}
}
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Get network nodes that are mentioned by the formula.]
Description [Get network nodes that are mentioned by the formula.]
SideEffects []
******************************************************************************/
static void
GetFormulaNodes(
Ntk_Network_t *network,
Ctlp_Formula_t *F,
array_t *formulaNodes)
{
if (F == NIL(Ctlp_Formula_t))
return;
if (Ctlp_FormulaReadType(F) == Ctlp_ID_c) {
char *nodeNameString = Ctlp_FormulaReadVariableName(F);
Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString);
assert(node);
array_insert_last(Ntk_Node_t *, formulaNodes, node);
return;
}
GetFormulaNodes(network, Ctlp_FormulaReadRightChild(F), formulaNodes);
GetFormulaNodes(network, Ctlp_FormulaReadLeftChild(F), formulaNodes);
}
/**Function********************************************************************
Synopsis [Get the fan-in latches of those already in the table.]
Description [Get the fan-in latches of those already in the table.]
SideEffects []
******************************************************************************/
static void
GetFaninLatches(
Ntk_Node_t *node,
st_table *visited,
st_table *absVarTable)
{
if (st_is_member(visited, node))
return;
st_insert(visited, node, (char *)0);
if (Ntk_NodeTestIsLatch(node))
st_insert(absVarTable, node, (char *)0);
else {
int i;
Ntk_Node_t *fanin;
Ntk_NodeForEachFanin(node, i, fanin) {
GetFaninLatches(fanin, visited, absVarTable);
}
}
}
/**Function********************************************************************
Synopsis [Add nodes for wires referred to in formula to nodesTable.]
SideEffects []
******************************************************************************/
static void
NodeTableAddCtlFormulaNodes(
Ntk_Network_t *network,
Ctlp_Formula_t *formula,
st_table * nodesTable )
{
if (formula == NIL(Ctlp_Formula_t))
return;
if ( Ctlp_FormulaReadType( formula ) == Ctlp_ID_c ) {
char *nodeNameString = Ctlp_FormulaReadVariableName( formula );
Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
if( node )
st_insert( nodesTable, ( char *) node, NIL(char) );
return;
}
NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadRightChild( formula ), nodesTable );
NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadLeftChild( formula ), nodesTable );
}