VIS

src/eqv/eqvCmd.c File Reference

#include "eqvInt.h"
Include dependency graph for eqvCmd.c:

Go to the source code of this file.

Functions

static int CommandCombEquivalence (Hrc_Manager_t **hmgr, int argc, char **argv)
static int CommandSeqEquivalence (Hrc_Manager_t **hmgr, int argc, char **argv)
static void TimeOutHandle (void)
void Eqv_Init (void)
void Eqv_End (void)

Variables

static char rcsid[] UNUSED = "$Id: eqvCmd.c,v 1.20 2009/04/11 18:26:04 fabio Exp $"
static jmp_buf timeOutEnv

Function Documentation

static int CommandCombEquivalence ( Hrc_Manager_t **  hmgr,
int  argc,
char **  argv 
) [static]

AutomaticStart

Function********************************************************************

Synopsis [This function sits between the command line and the top level function which checks combinational equivalence.]

Description [The function parses the command line and generates the arguments to the top level routine.]

SideEffects [If the variables of the network present at the current node of the existing hierarchy have not been ordered, they get ordered.]

SeeAlso [Eqv_NetworkVerifyCombinationalEquivalence]

CommandName [comb_verify]

CommandSynopsis [verify the combinational equivalence of two flattened networks]

CommandArguments [ \[-b\] \[-f <filename>\] \[-h\] \[-o <ordering method>\] \[-t <timeOut>\] \[-1 <partition method>\] \[-2 <partition method>\] \[-i\] <filename1> \[<filename2>\] ]

CommandDescription [This command verifies the combinational equivalence of two flattened networks. In particular, any set of functions (the roots), defined over any set of intermediate variables (the leaves), can be checked for equivalence between the two networks. Roots and leaves are subsets of the nodes of a network, with the restriction that the leaves should form a complete support for the roots. The correspondence between the roots and the leaves in the two networks is specified in a file given by the option -f <filename>. The default option assumes that the roots are the combinational outputs and the leaves are the combinational inputs.

When there is a pseudo input in the set of leaves, the range of values it can take should be the same as that of the multi-valued variable corresponding to it, for comb_verify to function correctly. This restriction will be removed in future.

There are two ways to do combinational verification. In the first mode, two BLIF-MV files are given as arguments to the command, e.g.

  vis> comb_verify foo.mv bar.mv
  

Verification is done for the flattened networks at the root nodes of the two BLIF-MV hierarchies. In any error messages printed, "network1" refers to the first file, and "network2" refers to the second. Both of these networks are freed at the end of the command. This mode is totally independent from any existing hierarchy previously read in.

In the second mode, it is assumed that a hierarchy has already been read in. Then, comb_verify can be called with a single BLIF-MV file, and this will do the comparison between the network present at the current node ("network1") and the network corresponding to the root node of the hierarchy in the BLIF-MV file("network2"). A typical sequence of commands is:

  vis> read_blifmv foo.mv
  vis> init_verify
  vis> comb_verify bar.mv
  

If a hierarchy has been read in but a flattened network does not exist at the current node (flatten_hierarchy has not been invoked), the command does nothing. If a network exists at the current node, but the variables haven't been ordered, then the variables are ordered and a partition created. This partition is freed at the end. A side-effect is that the variables are ordered. If a partition exists, then it is used if the vertices corresponding to the roots specified are present in it, otherwise a new partition is created with the current ordering. The partition created for the new network read in is always freed at the end.

Command options:

-b

Specifies that the files are BLIF files and not BLIF-MV files.

-f <filename>

Provides the correspondence between the leaves and roots of network1 and network2. If this option is not used, it is assumed that the correspondence is by name, except that two latch inputs match if either they have the same name or the corresponding latch outputs have the same name. Leaves are the combinational inputs, and roots are the combinational outputs.

-h

Print the command usage.

-t <timeOut>

Time in seconds allowed to perform equivalence checking. The default is infinity.

-o <ordering method>

Specifies the ordering method to be used for assigning a common ordering to the leaves of network1 and network2. If this option is not used, ordering is done using a default method. Currently, only the default method is available.

-1 <partition method>

Specifies the partitioning method to be used for network1. Supported methods are "total", "partial", and "inout" (see the command build_partition_mdds for more information). If this option is not specified, then the default method "inout" is used.

-2 <partition method>

Specifies the partitioning method to be used for network2. Supported methods are "total", "partial", and "inout" (see the command build_partition_mdds for more information). If this option is not specified, then default method "inout" is used.

-i

Print Bdd statistics.

]

Definition at line 225 of file eqvCmd.c.

{
  static int                   timeOutPeriod;
  static Hrc_Manager_t        *hmgr1;
  static Hrc_Manager_t        *hmgr2;
  static Ntk_Network_t        *network1;
  static Ntk_Network_t        *network2;
  int                          c;
  int                          check;
  FILE                        *fp;
  FILE                        *inputFile = NIL(FILE);
  char                        *fileName1;
  char                        *fileName2;
  char                        *name1;
  char                        *name2;
  st_generator                *gen;
  static Part_PartitionMethod  partMethod1;
  static Part_PartitionMethod  partMethod2;
  static OFT                   AssignCommonOrder;
  static st_table             *inputMap;
  static st_table             *outputMap;
  st_table                    *rootsTable = NIL(st_table);
  st_table                    *leavesTable = NIL(st_table);
  boolean                      fileFlag = FALSE;
  boolean                      equivalent;
  boolean                      printBddInfo = FALSE;
  static boolean               execMode; /* FALSE: verify against current network,
                                            TRUE:  verify the two given networks */
  boolean isBlif = FALSE;

  /*
   * These are the default values.  These variables must be declared static
   * to avoid lint warnings.  Since they are static, we must reinitialize
   * them outside of the variable declarations.
   */
  timeOutPeriod     = 0;
  hmgr1             = NIL(Hrc_Manager_t);
  hmgr2             = NIL(Hrc_Manager_t);
  partMethod1       = Part_Default_c;
  partMethod2       = Part_Default_c;
  AssignCommonOrder = DefaultCommonOrder;
  inputMap          = NIL(st_table);
  outputMap         = NIL(st_table);

  error_init();
  util_getopt_reset();
  while((c = util_getopt(argc, argv, "bf:o:1:2:ht:i")) != EOF) {
    switch(c) {
      case 'b':
        isBlif = TRUE;
        break;
      case 'f':
        if((inputFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 1)) ==
           NIL(FILE)) {
          (void) fprintf(vis_stderr, "** eqv error: File %s not found.\n", util_optarg);
          goto usage;
        }
        fileFlag = 1;
        break;
      case 'o':
        /* The following line causes a seg fault, because
           FindOrderingMethod() always returns NULL, and currently
           only DefaultCommonOrder is used.
        AssignCommonOrder = FindOrderingMethod();
        */
        /* The programmer supplies and modifies this function if any new
           ordering method is introduced. FindOrderingMethod() should return
           the type OFT. */
        break;
      case 't':
        timeOutPeriod = atoi(util_optarg);
        break;
      case '1':
        if(!strcmp(util_optarg, "total")) {
          partMethod1 =  Part_Total_c;
        }
        else
          if(!strcmp(util_optarg, "partial")) {
          partMethod1 =  Part_Partial_c;
          }
        else
          if(!strcmp(util_optarg, "inout")) {
            partMethod1 = Part_InOut_c;
          }
          else {
            (void) fprintf(vis_stderr, "** eqv error: Unknown partition method 1\n");
            goto usage;
          }
        break;
      case '2':
        if(!strcmp(util_optarg, "total")) {
          partMethod2 =  Part_Total_c;
        }
        else
          if(!strcmp(util_optarg, "partial")) {
          partMethod2 =  Part_Partial_c;
          }
        else
          if(!strcmp(util_optarg, "inout")) {
            partMethod2 = Part_InOut_c;
          }
          else {
            (void) fprintf(vis_stderr, "** eqv error: Unknown partition method 2\n");
            goto usage;
          }
        break;
      case 'i':
        printBddInfo = TRUE;
        break;
      case 'h':
        goto usage;
      default :
        goto usage;
    }
  }
  if(argc == 1) {
    goto usage;
  }

  if(argc == util_optind+1) {
    execMode = FALSE;
  }
  else
    if(argc == util_optind+2) {
      execMode = TRUE;
    }
    else {
      error_append("** eqv error: Improper number of arguments.\n");
      (void) fprintf(vis_stderr, "%s", error_string());
      goto usage;
    }
  if(execMode == FALSE) {
    hmgr1 = *hmgr;
    if(Hrc_ManagerReadCurrentNode(hmgr1) == NIL(Hrc_Node_t)) {
      (void) fprintf(vis_stderr, "** eqv error: The hierarchy manager is empty.  Read in design.\n");
      return 1;
    }
    network1 = (Ntk_Network_t *) Hrc_NodeReadApplInfo(
                    Hrc_ManagerReadCurrentNode(hmgr1), NTK_HRC_NODE_APPL_KEY);
    if(network1 == NIL(Ntk_Network_t)) {
      (void) fprintf(vis_stderr, "** eqv error: There is no network. Use flatten_hierarchy.\n");
      return 1;
    }
    if(Ntk_NetworkReadApplInfo(network1, PART_NETWORK_APPL_KEY) == NIL(void)) {
      (void) fprintf(vis_stderr, "** eqv error: Network has not been partitioned. Use build_partition_mdds.\n");
      return 1;
    }
    fileName2 = argv[util_optind];
    if(isBlif) {
      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        goto usage;
      }
    }
    else {
      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
        return 1;
      }
      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr2 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        return 1;
      }
    }
    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
                                           TRUE, (lsList) NULL);
    if(network2 == NIL(Ntk_Network_t)) {
      Hrc_ManagerFree(hmgr2);
      (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
      return 1;
    }

  }
  else {
    fileName1 = argv[util_optind];
    fileName2 = argv[util_optind+1];
    if(isBlif) {
      if((hmgr1 = Io_BlifRead(fileName1, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
        return 1;
      }
      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
    }
    else {
      if((fp = Cmd_FileOpen(fileName1, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName1);
        return 1;
      }
      hmgr1 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr1 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
        goto usage;
      }
      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr2 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
    }
    network1 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr1),
                                           TRUE, (lsList) NULL);
    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
                                           TRUE, (lsList) NULL);

    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
      if(network1 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
      }
      if(network2 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
      }
      Hrc_ManagerFree(hmgr1);
      Hrc_ManagerFree(hmgr2);
      return 1;
    }
    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
      if(network1 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
      }
      if(network2 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
      }
      Hrc_ManagerFree(hmgr1);
      Hrc_ManagerFree(hmgr2);
      return 1;
    }
  }

  if(Ntk_NetworkReadNumCombInputs(network1) !=
     Ntk_NetworkReadNumCombInputs(network2)) {
    error_append("** eqv error: Different number of inputs in the two networks.\n");
    if(!fileFlag) {
      if(execMode) {
        Hrc_ManagerFree(hmgr1);
        Ntk_NetworkFree(network1);
      }
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      (void) fprintf(vis_stderr, "%s", error_string());
      return 1;
    }
  }

  if(fileFlag) {
    rootsTable = st_init_table(strcmp, st_strhash);
    leavesTable = st_init_table(strcmp, st_strhash);
    check = ReadRootLeafMap(inputFile, rootsTable, leavesTable);
    fclose(inputFile);
    switch (check) {
      case 0 : /* error */
        st_free_table(rootsTable);
        st_free_table(leavesTable);
        (void) fprintf(vis_stderr, "** eqv error: No data in the input file.\n");
        if(execMode) {
          Hrc_ManagerFree(hmgr1);
          Ntk_NetworkFree(network1);
        }
        Hrc_ManagerFree(hmgr2);
        Ntk_NetworkFree(network2);
        return 1;
    case 1 : /* leaves only */
        st_free_table(rootsTable);
        inputMap = MapNamesToNodes(network1, network2, leavesTable);
        st_foreach_item(leavesTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(leavesTable);
        if(inputMap == NIL(st_table)) {
          (void) fprintf(vis_stderr, "%s", error_string());
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          return 1;
        }
        if((outputMap = MapCombOutputsByName(network1, network2)) ==
           NIL(st_table)) {
          st_free_table(inputMap);
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          (void) fprintf(vis_stderr, "%s", error_string());
          return 1;
        }
        if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
                                       outputMap)){
          st_free_table(inputMap);
          st_free_table(outputMap);
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          (void) fprintf(vis_stderr, "%s", error_string());
          return 1;
        }
        break;
    case 2 : /* roots only */
        st_free_table(leavesTable);
        outputMap = MapNamesToNodes(network1, network2, rootsTable);
        st_foreach_item(rootsTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(rootsTable);
        if(outputMap ==NIL(st_table)) {
          (void) fprintf(vis_stderr, "%s", error_string());
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          return 1;
        }
        if((inputMap = MapCombInputsByName(network1, network2)) ==
           NIL(st_table)) {
          st_free_table(outputMap);
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          (void) fprintf(vis_stderr, "%s", error_string());
          return 1;
        }
        if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
                                       outputMap)){
          st_free_table(inputMap);
          st_free_table(outputMap);
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          return 1;
        }
        break;
    case 3 : /* both leaves and roots */
        inputMap = MapNamesToNodes(network1, network2, leavesTable);
        st_foreach_item(leavesTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(leavesTable);
        outputMap = MapNamesToNodes(network1, network2, rootsTable);
        st_foreach_item(rootsTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(rootsTable);
        if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
          (void) fprintf(vis_stderr, "%s", error_string());
          if(inputMap) {
            st_free_table(inputMap);
          }
          if(outputMap) {
            st_free_table(outputMap);
          }
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          return 1;
        }
        if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
                                       outputMap)){
          st_free_table(inputMap);
          st_free_table(outputMap);
          if(execMode) {
            Hrc_ManagerFree(hmgr1);
            Ntk_NetworkFree(network1);
          }
          Hrc_ManagerFree(hmgr2);
          Ntk_NetworkFree(network2);
          (void) fprintf(vis_stderr, "%s", error_string());
          return 1;
        }
        break;
    }
  }
  else {
    inputMap = MapCombInputsByName(network1, network2);
    outputMap = MapCombOutputsByName(network1, network2);
    if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
      if(inputMap) {
        st_free_table(inputMap);
      }
      if(outputMap) {
        st_free_table(outputMap);
      }
      if(execMode) {
        Hrc_ManagerFree(hmgr1);
        Ntk_NetworkFree(network1);
      }
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      (void) fprintf(vis_stderr, "%s", error_string());
      return 1;
    }
  }

  /* Start the timer before calling the equivalence checker. */
  if (timeOutPeriod > 0){
    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
    (void) alarm(timeOutPeriod);
    if (setjmp(timeOutEnv) > 0) {
      (void) fprintf(vis_stderr, "Timeout occurred after %d seconds.\n", timeOutPeriod);
      alarm(0);
      return 1;
    }
  }

  equivalent = Eqv_NetworkVerifyCombinationalEquivalence(network1, network2,
                                                         inputMap, outputMap,
                                                         AssignCommonOrder,
                                                         partMethod1,
                                                         partMethod2);

  if(equivalent) {
    (void) fprintf(vis_stdout, "Networks are combinationally equivalent.\n\n");
  }
  else {
    (void) fprintf(vis_stdout, "%s", error_string());
    (void) fprintf(vis_stdout, "Networks are NOT combinationally equivalent.\n\n");
  }

  if (printBddInfo) {
    bdd_print_stats(Ntk_NetworkReadMddManager(network1), vis_stdout);
  }

  st_free_table(inputMap);
  st_free_table(outputMap);
  if(execMode) {
    Hrc_ManagerFree(hmgr1);
    Ntk_NetworkFree(network1);
  }
  Hrc_ManagerFree(hmgr2);
  Ntk_NetworkFree(network2);

  alarm(0);
  return 0; /* normal exit */

  usage:
  (void) fprintf(vis_stderr, "usage: comb_verify [-b] [-f filename] [-h] [-o ordering method] [-t time]\n");
  (void) fprintf(vis_stderr, "                   [-1 partMethod1] [-2 partMethod2] [-i] file1 [file2]\n");
  (void) fprintf(vis_stderr, "   -b        input files are BLIF\n");
  (void) fprintf(vis_stderr, "   -f file   variable name correspondence file\n");
  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
  (void) fprintf(vis_stderr, "   -o method variable ordering method\n");
  (void) fprintf(vis_stderr, "   -t time   time out period (in seconds)\n");
  (void) fprintf(vis_stderr, "   -1 method partitioning method for network1\n");
  (void) fprintf(vis_stderr, "   -2 method partitioning method for network2\n");
  (void) fprintf(vis_stderr, "   -i        print Bdd statistics\n");
  return 1;             /* error exit */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int CommandSeqEquivalence ( Hrc_Manager_t **  hmgr,
int  argc,
char **  argv 
) [static]

Function********************************************************************

Synopsis [This function sits between the command line and the main routine of sequential verification.]

Description [The function parses the command line.]

SideEffects []

SeeAlso [Eqv_NetworkVerifySequentialEquivalence]

CommandName [seq_verify]

CommandSynopsis [verify the sequential equivalence of two flattened networks]

CommandArguments [\[-b\] \[-f <filename>\] \[-h\] \[-p <partition method>\] \[-t <timeOut>\] \[-B\] \[-i\] \[-r\] <filename> \[<filename>\]]

CommandDescription [Please read the documentation for the command comb_verify before reading on. The concepts of roots and leaves in this command are the same as for comb_verify, except for an added constraint: the set of leaves has to be the set of all primary inputs. This obviously produces the constraint that both networks have the same number of primary inputs. Moreover, no pseudo inputs should be present in the two networks being compared. The set of roots can be an arbitrary subset of nodes.

The command verifies whether any state, where the values of two corresponding roots differ, can be reached from the set of initial states of the product machine. If this happens, a debug trace is provided.

The sequential verification is done by building the product finite state machine.

The command has two execution modes, just as for comb_verify. In the first mode, two BLIF-MV files are given as arguments to the command:

  vis> seq_verify foo.mv bar.mv
  

In the second mode, a single BLIF-MV file is taken. This is network2. It is assumed that network1 is from a hierarchy that has already been read in. If a network is present at the current node (i.e. flatten_hierarchy has been executed), it is used for verification; otherwise the command does nothing.

  vis> read_blifmv foo.mv
  vis> flatten_hierarchy
  vis> seq_verify bar.mv
  

Command options:

-b

Specifies that the input files are BLIF files.

-f <filename>

Provides the correspondence between the leaves and roots of network1 and network2. leaves has to be the set of primary inputs of the networks. roots can be any subset of nodes. If this option is not used, it is assumed that the correspondence is by name, and that the roots are the combinational outputs.

-h

Print the command usage.

-p <partition method>

Specifies the partitioning method for the product machine. Supported methods are "total", "partial", and "inout" (see the command build_partition_mdds for more information). If this option is not specified, then the default method "inout" is used.

-t <timeOut>

Time in seconds allowed to perform equivalence checking. The default is infinity.

-B

Use backward image computation to traverse the state space of the product machine. By default, forward image computaion is used.

-i

Print BDD statistics. This is the only way to see BDD stastics during this command. print_bdd_stats after this command doesn't show information related to this command.

-r
Enable BDD reordering during the equivalence check. Note that dynamic_var_ordering has no effect on whether reordering is enabled during the execution of seq_verify.

]

Definition at line 820 of file eqvCmd.c.

{
  static int            timeOutPeriod;
  static Hrc_Manager_t *hmgr1;
  static Hrc_Manager_t *hmgr2;
  static Ntk_Network_t *network1;
  static Ntk_Network_t *network2;
  int                   c;
  int                   check;
  FILE                 *fp;
  static FILE          *inputFile;
  char                 *fileName1;
  char                 *fileName2;
  char                 *name1;
  char                 *name2;
  st_generator         *gen;
  static Part_PartitionMethod partMethod;
  st_table             *outputMap = NIL(st_table);
  st_table             *inputMap = NIL(st_table);
  st_table             *rootsTable = NIL(st_table);
  st_table             *leavesTable = NIL(st_table);
  static boolean        fileFlag;
  static boolean        execMode; /* FALSE: verify against the current network,
                                     TRUE:  verify the two networks */
  static boolean        equivalent;
  boolean               isBlif = FALSE;
  boolean               printBddInfo = FALSE;
  static boolean        useBackwardReach;
  boolean               reordering = FALSE;

  /*
   * These are the default values.  These variables must be declared static
   * to avoid lint warnings.  Since they are static, we must reinitialize
   * them outside of the variable declarations.
   */
  timeOutPeriod    = 0;
  hmgr1            = NIL(Hrc_Manager_t);
  hmgr2            = NIL(Hrc_Manager_t);
  inputFile        = NIL(FILE);
  partMethod       = Part_Default_c;
  fileFlag         = FALSE;
  equivalent       = FALSE;
  useBackwardReach = FALSE;

  error_init();
  util_getopt_reset();
  while((c = util_getopt(argc, argv, "bBf:p:hFt:ir")) != EOF) {
    switch(c) {
    case 'b':
      isBlif = TRUE;
      break;
    case 'f':
      if((inputFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 1)) ==
         NIL(FILE)) {
        (void) fprintf(vis_stderr,
                       "** eqv error: File %s not found.\n", util_optarg);
        return 1;
      }
      fileFlag = 1;
      break;
    case 'p':
      if(!strcmp(util_optarg, "total")) {
        partMethod =  Part_Total_c;
      } else {
        if(!strcmp(util_optarg, "partial")) {
          partMethod =  Part_Partial_c;
        } else {
          if(!strcmp(util_optarg, "inout")) {
            partMethod = Part_InOut_c;
          } else {
            (void) fprintf(vis_stderr,
                           "** eqv error: Unknown partition method\n");
            goto usage;
          }
        }
      }
      break;
    case 't':
      timeOutPeriod = atoi(util_optarg);
      break;
    case 'B':
      useBackwardReach = TRUE;
      break;
    case 'h':
      goto usage;
    case 'i':
      printBddInfo = TRUE;
      break;
    case 'r':
      reordering = TRUE;
      break;
    default:
      goto usage;
    }
  }
  if(argc == 1) {
    goto usage;
  }
  if(argc == util_optind+1) {
    execMode = FALSE;
  }
  else
    if(argc == util_optind+2) {
      execMode = TRUE;
    }
    else {
      error_append("** eqv error: Improper number of arguments.\n");
      (void) fprintf(vis_stderr, "%s", error_string());
      goto usage;
    }
  if(execMode == FALSE) {
    hmgr1 = *hmgr;
    if(Hrc_ManagerReadCurrentNode(hmgr1) == NIL(Hrc_Node_t)) {
      (void) fprintf(vis_stderr, "** eqv error: The hierarchy manager is empty.  Read in design.\n");
      return 1;
    }
    network1 = (Ntk_Network_t *) Hrc_NodeReadApplInfo(
                    Hrc_ManagerReadCurrentNode(hmgr1), NTK_HRC_NODE_APPL_KEY);
    if(network1 == NIL(Ntk_Network_t)) {
      (void) fprintf(vis_stderr, "** eqv error: There is no network. Use flatten_hierarchy.\n");
      return 1;
    }
    if(!Ntk_NetworkReadNumLatches(network1)) {
      (void) fprintf(vis_stderr, "** eqv error: No latches present in the current network. Use comb_verify.\n");
      return 1;
    }
    fileName2 = argv[util_optind];
    if(isBlif) {
      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        goto usage;
      }
    }
    else {
      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
        return 1;
      }
      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr2 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        return 1;
      }
    }
    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
                                           TRUE, (lsList) NULL);
    if(network2 == NIL(Ntk_Network_t)) {
      Hrc_ManagerFree(hmgr2);
      (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
      return 1;
    }
    if(!Ntk_NetworkReadNumLatches(network2)) {
      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName2);
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      return 1;
    }
  }
  else {
    fileName1 = argv[util_optind];
    fileName2 = argv[util_optind+1];
    if(isBlif) {
      if((hmgr1 = Io_BlifRead(fileName1, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
        return 1;
      }
      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
    }
    else {
      if((fp = Cmd_FileOpen(fileName1, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName1);
        return 1;
      }
      hmgr1 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr1 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
        goto usage;
      }
      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
        (void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
      fclose(fp);
      if(hmgr2 == NIL(Hrc_Manager_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
        if(hmgr1) {
          Hrc_ManagerFree(hmgr1);
        }
        return 1;
      }
    }
    network1 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr1),
                                           TRUE, (lsList) NULL);
    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
                                           TRUE, (lsList) NULL);
    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
      if(network1 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
      }
      if(network2 == NIL(Ntk_Network_t)) {
        (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
      }
      Hrc_ManagerFree(hmgr1);
      Hrc_ManagerFree(hmgr2);
      return 1;
    }

    if(!Ntk_NetworkReadNumLatches(network1)) {
      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName1);
      Hrc_ManagerFree(hmgr1);
      Ntk_NetworkFree(network1);
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      return 1;
    }
    if(!Ntk_NetworkReadNumLatches(network2)) {
      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName2);
      Hrc_ManagerFree(hmgr1);
      Ntk_NetworkFree(network1);
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      return 1;
    }
  }
  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
     Ntk_NetworkReadNumInputs(network1)) {
    error_append("** eqv error: Pseudo inputs present in network1. Unable to do verification.\n");
    (void) fprintf(vis_stderr, "%s", error_string());
    if(execMode) {
      Hrc_ManagerFree(hmgr1);
      Ntk_NetworkFree(network1);
    }
    Hrc_ManagerFree(hmgr2);
    Ntk_NetworkFree(network2);
    return 1;
  }
  if(Ntk_NetworkReadNumPrimaryInputs(network2) !=
     Ntk_NetworkReadNumInputs(network2)) {
    error_append("** eqv error: Pseudo inputs present in network2. Unable to do verification.\n");
    (void) fprintf(vis_stderr, "%s", error_string());
    if(execMode) {
      Hrc_ManagerFree(hmgr1);
      Ntk_NetworkFree(network1);
    }
    Hrc_ManagerFree(hmgr2);
    Ntk_NetworkFree(network2);
    return 1;
  }
  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
     Ntk_NetworkReadNumPrimaryInputs(network2)) {
    error_append("** eqv error: Different number of inputs in the two networks.\n");
    (void) fprintf(vis_stderr, "%s", error_string());
    if(execMode) {
      Hrc_ManagerFree(hmgr1);
      Ntk_NetworkFree(network1);
    }
    Hrc_ManagerFree(hmgr2);
    Ntk_NetworkFree(network2);
    return 1;
  }

  /* Start the timer before calling the equivalence checker. */
  if (timeOutPeriod > 0){
    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
    (void) alarm(timeOutPeriod);
    if (setjmp(timeOutEnv) > 0) {
      (void) fprintf(vis_stderr, "Timeout occurred after %d seconds.\n",
                     timeOutPeriod);
      alarm(0);
      return 1;
    }
  }

  if(fileFlag) {
    rootsTable = st_init_table(strcmp, st_strhash);
    leavesTable = st_init_table(strcmp, st_strhash);
    check = ReadRootLeafMap(inputFile, rootsTable, leavesTable);
    fclose(inputFile);
    if(check == 0) {
      st_free_table(rootsTable);
      st_free_table(leavesTable);
      (void) fprintf(vis_stderr, "** eqv error: No data in the input file\n");
      alarm(0);
      return 1;
    }
    switch (check) {
    case 1 :
      st_free_table(rootsTable);
      outputMap = MapPrimaryOutputsByName(network1, network2);
      if((outputMap == NIL(st_table)) || !TestLeavesAreValid(network1,
                                                             network2,
                                                             leavesTable)) {
        st_foreach_item(leavesTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(leavesTable);
        if(outputMap) {
          st_free_table(outputMap);
        }
        (void) fprintf(vis_stderr, "%s", error_string());
        if(execMode) {
          Hrc_ManagerFree(hmgr1);
          Ntk_NetworkFree(network1);
        }
        Hrc_ManagerFree(hmgr2);
        Ntk_NetworkFree(network2);
        (void) fprintf(vis_stderr, "%s", error_string());
        alarm(0);
        return 1;
      }
      equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
                                                          network2,
                                                          NIL(st_table),
                                                          leavesTable,
                                                          partMethod,
                                                          useBackwardReach,
                                                          reordering);
      st_foreach_item(leavesTable, gen, &name1, &name2) {
        FREE(name1);
        FREE(name2);
      }
      st_free_table(leavesTable);
      break;
    case 2 :
      st_free_table(leavesTable);
      inputMap = MapPrimaryInputsByName(network1, network2);

      if((inputMap == NIL(st_table)) || !TestRootsAreValid(network1,
                                                           network2,
                                                           rootsTable)) {
        st_foreach_item(rootsTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(rootsTable);
        if(inputMap) {
          st_free_table(inputMap);
        }
        (void) fprintf(vis_stderr, "%s", error_string());
        if(execMode) {
          Hrc_ManagerFree(hmgr1);
          Ntk_NetworkFree(network1);
        }
        Hrc_ManagerFree(hmgr2);
        Ntk_NetworkFree(network2);
        alarm(0);
        return 1;
      }
      equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
                                                          network2,
                                                          rootsTable,
                                                          NIL(st_table),
                                                          partMethod,
                                                          useBackwardReach,
                                                          reordering);
      st_foreach_item(rootsTable, gen, &name1, &name2) {
        FREE(name1);
        FREE(name2);
      }
      st_free_table(rootsTable);
      break;
    case 3 :
      if(TestRootsAreValid(network1, network2, rootsTable) &&
         TestLeavesAreValid(network1, network2, leavesTable)) {
        equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
                                                            network2,
                                                            rootsTable,
                                                            leavesTable,
                                                            partMethod,
                                                            useBackwardReach,
                                                            reordering);
        st_foreach_item(rootsTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(rootsTable);
        st_foreach_item(leavesTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(leavesTable);
      }
      else {
        if(execMode) {
          Hrc_ManagerFree(hmgr1);
          Ntk_NetworkFree(network1);
        }
        Hrc_ManagerFree(hmgr2);
        Ntk_NetworkFree(network2);
        st_foreach_item(rootsTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(rootsTable);
        st_foreach_item(leavesTable, gen, &name1, &name2) {
          FREE(name1);
          FREE(name2);
        }
        st_free_table(leavesTable);
        (void) fprintf(vis_stderr, "%s", error_string());
        alarm(0);
        return 1;
      }
    }
  }
  else {
    outputMap = MapPrimaryOutputsByName(network1, network2);
    inputMap = MapPrimaryInputsByName(network1, network2);
    if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
      if(inputMap) {
        st_free_table(inputMap);
      }
      if(outputMap) {
        st_free_table(outputMap);
      }
      if(execMode) {
        Hrc_ManagerFree(hmgr1);
        Ntk_NetworkFree(network1);
      }
      Hrc_ManagerFree(hmgr2);
      Ntk_NetworkFree(network2);
      (void) fprintf(vis_stderr, "%s", error_string());
      alarm(0);
      return 1;    /* all primary outputs do not match */
    }
    st_free_table(inputMap);
    st_free_table(outputMap);
    equivalent = Eqv_NetworkVerifySequentialEquivalence(network1, network2,
                                                        NIL(st_table),
                                                        NIL(st_table),
                                                        partMethod,
                                                        useBackwardReach,
                                                        reordering);
  }
  if(equivalent) {
    (void) fprintf(vis_stdout, "Networks are sequentially equivalent.\n\n");
  }
  else {
    (void) fprintf(vis_stdout,
                   "Networks are NOT sequentially equivalent.\n\n");
  }

  if (printBddInfo) {
    bdd_print_stats(Ntk_NetworkReadMddManager(network2), vis_stdout);
  }

  if(execMode) {
    Hrc_ManagerFree(hmgr1);
    Ntk_NetworkFree(network1);
  }
  Hrc_ManagerFree(hmgr2);
  Ntk_NetworkFree(network2);

  alarm(0);
  return 0;  /* normal exit */

  usage :
  (void) fprintf(vis_stderr, "usage: seq_verify [-b] [-f filename] [-h] [-p partition method] [-t time] [-B]\n\t\t  [-i] [-r] file1 [file2]\n");
  (void) fprintf(vis_stderr, "   -b        input files are BLIF\n");
  (void) fprintf(vis_stderr, "   -f file   variable name correspondence file\n");
  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
  (void) fprintf(vis_stderr, "   -p method partitioning method for product machine\n");
  (void) fprintf(vis_stderr, "   -t time   time out period (in seconds)\n");
  (void) fprintf(vis_stderr, "   -B        use backward image computation\n");
  (void) fprintf(vis_stderr, "   -i        print BDD statistics\n");
  (void) fprintf(vis_stderr, "   -r        enable BDD variable reordering\n");
  return 1;    /* error exit */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void Eqv_End ( void  )

Function********************************************************************

Synopsis [This function ends the eqv package.]

SideEffects []

SeeAlso [Eqv_Init()]

Definition at line 89 of file eqvCmd.c.

{
}

Here is the caller graph for this function:

void Eqv_Init ( void  )

AutomaticEnd Function********************************************************************

Synopsis [This function initializes the eqv package.]

SideEffects []

SeeAlso [Eqv_End()]

Definition at line 73 of file eqvCmd.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void TimeOutHandle ( void  ) [static]

Function********************************************************************

Synopsis [Handle function for timeout.]

Description [This function is called when the time out occurs.]

SideEffects []

Definition at line 1315 of file eqvCmd.c.

{
  longjmp(timeOutEnv, 1);
}

Here is the caller graph for this function:


Variable Documentation

jmp_buf timeOutEnv [static]

Definition at line 43 of file eqvCmd.c.

char rcsid [] UNUSED = "$Id: eqvCmd.c,v 1.20 2009/04/11 18:26:04 fabio Exp $" [static]

CFile***********************************************************************

FileName [eqvCmd.c]

PackageName [eqv]

Synopsis [Implements the eqv commands.]

Description [This file initializes the eqv package and provides the interface between the command line and the top level routine which does the equivalence checking.]

Author [Shaz Qadeer]

Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. 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.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]

Definition at line 38 of file eqvCmd.c.