source: vis_dev/vis-2.3/src/io/ioCheck.c @ 40

Last change on this file since 40 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 27.6 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [ioCheck.c]
4
5  PackageName [io]
6
7  Synopsis    [Routines to test if a blif-mv file is consistent.]
8
9  Description [Routines to test if a blif-mv file is consistent. They are
10  also responsible for setting several internal data structures. Here are
11  the list of checks we can do on an hsis network. For each model, we first
12  check if there is no node labeled both as PI and PS or both as PI and PO.
13  Then, for each subcircuit in the model, the compatibllity of the interface
14  is verified namewise and rangewise. This is detailed below. Then,
15  we verify that there is no combinational cycle in any model.  Furthermore,
16  for each latch in the model, we make sure that the input and the output
17  of the latch are of the same type and that every latch has a reset table. 
18  Finally, we check to see if each variable is an output of at
19  most one table. As for the check to be done for a subcircuit, we first check
20  if the model to be instantiated is present in the hmanager. Then, we
21  test if all the formal variables in the subcircuit definition exist
22  in the model and at the same time they are of the same type of the
23  corresponding actual variables. More thoroughly, we have to check
24  if a flattened network has no cycle, but it is not currently implemented.]
25
26  SeeAlso     []
27
28  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
29
30  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
31  All rights reserved.
32
33  Permission is hereby granted, without written agreement and without license
34  or royalty fees, to use, copy, modify, and distribute this software and its
35  documentation for any purpose, provided that the above copyright notice and
36  the following two paragraphs appear in all copies of this software.
37
38  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
39  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
40  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
41  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
43  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
44  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
45  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
46  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
47  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
48
49******************************************************************************/
50
51#include "ioInt.h"
52
53static char rcsid[] UNUSED = "$Id: ioCheck.c,v 1.11 2005/04/16 06:17:45 fabio Exp $";
54
55/*---------------------------------------------------------------------------*/
56/* Constant declarations                                                     */
57/*---------------------------------------------------------------------------*/
58
59
60/*---------------------------------------------------------------------------*/
61/* Type declarations                                                         */
62/*---------------------------------------------------------------------------*/
63
64
65/*---------------------------------------------------------------------------*/
66/* Stucture declarations                                                     */
67/*---------------------------------------------------------------------------*/
68
69
70/*---------------------------------------------------------------------------*/
71/* Variable declarations                                                     */
72/*---------------------------------------------------------------------------*/
73
74
75/*---------------------------------------------------------------------------*/
76/* Macro declarations                                                        */
77/*---------------------------------------------------------------------------*/
78
79
80/**AutomaticStart*************************************************************/
81
82/*---------------------------------------------------------------------------*/
83/* Static function prototypes                                                */
84/*---------------------------------------------------------------------------*/
85
86static boolean _IoModelTestMasterNodeConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode);
87static boolean _IoModelTestConnectionConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *subcktArray);
88static boolean _IoModelTestLatchConsistency(Hrc_Node_t *hnode);
89static boolean _IoModelTestResetConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *resetArray);
90static boolean _IoModelTestInternalConnectionConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode, boolean isVerbose);
91static boolean _IoModelTestIsAcyclic(Hrc_Model_t *model, Hrc_Node_t *hnode, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable);
92static void _IoModelTestIsAcyclicError(Hrc_Model_t *model, Var_Variable_t *var);
93static int _IoModelTestIsAcyclicRecursive(Hrc_Model_t *model, Hrc_Node_t *hnode, Var_Variable_t *var, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable, boolean isResetLogic);
94
95/**AutomaticEnd***************************************************************/
96
97
98/*---------------------------------------------------------------------------*/
99/* Definition of exported functions                                          */
100/*---------------------------------------------------------------------------*/
101
102
103/*---------------------------------------------------------------------------*/
104/* Definition of internal functions                                          */
105/*---------------------------------------------------------------------------*/
106
107/**Function********************************************************************
108
109  Synopsis    [Checks to see if a given blif-mv network is consistent.]
110
111  Description []
112
113  SideEffects []
114
115  SeeAlso     []
116
117******************************************************************************/
118boolean
119IoNetworkTestConsistency(
120  Hrc_Manager_t *hmgr, 
121  array_t *modelArray,
122  st_table *parserSubcktInfo,
123  st_table *parserResetInfo,
124  boolean isVerbose)
125{
126  char *subcktArray, *resetArray;
127  Hrc_Model_t *model;
128  Hrc_Node_t *hnode;
129  int i;
130
131  for (i=0; i < array_n(modelArray); i++){
132    model = array_fetch(Hrc_Model_t *,modelArray,i);
133
134    hnode = Hrc_ModelReadMasterNode(model);
135
136    if (_IoModelTestMasterNodeConsistency(model,hnode) == 0){
137      return 0;
138    }
139    /* the following st_lookup should return 1 */
140    (void)st_lookup(parserSubcktInfo,(char *)model,&subcktArray);
141    if ((array_t *)subcktArray != NIL(array_t)){
142      if (_IoModelTestConnectionConsistency(hmgr,model,hnode,(array_t *)subcktArray) == 0){
143        return 0;
144      }
145    }
146    /* the following st_lookup should return 1 */
147    (void)st_lookup(parserResetInfo,(char *)model,&resetArray);
148    if ((array_t *)resetArray != NIL(array_t)){
149      if (_IoModelTestResetConsistency(hmgr,model,hnode,(array_t *)resetArray) == 0){
150        return 0;
151      }
152    }
153    if (_IoModelTestLatchConsistency(hnode) == 0){
154      return 0;
155    }
156    if (_IoModelTestInternalConnectionConsistency(model,hnode,isVerbose) == 0){
157      return 0;
158    }
159  }
160  return 1;
161}
162
163/*---------------------------------------------------------------------------*/
164/* Definition of static functions                                            */
165/*---------------------------------------------------------------------------*/
166
167/**Function********************************************************************
168
169  Synopsis    [Checks to see if there is no inconsistency in a model.]
170
171  Description []
172
173  SideEffects []
174
175  SeeAlso     []
176
177******************************************************************************/
178static boolean
179_IoModelTestMasterNodeConsistency(
180  Hrc_Model_t *model,
181  Hrc_Node_t *hnode)
182{
183  char *varName;
184  Var_Variable_t *var;
185  st_generator *gen;
186
187  Hrc_NodeForEachVariable(hnode,gen,varName,var){
188    if (Var_VariableTestTypeConsistency(var) == 0){
189      st_free_gen(gen);
190      return 0;
191    }
192  }
193  return 1;
194}
195
196/**Function********************************************************************
197
198  Synopsis    [Checks to see if there is no inconsistency in subcircuit connections.]
199
200  Description []
201
202  SideEffects []
203
204  SeeAlso     []
205
206******************************************************************************/
207static boolean
208_IoModelTestConnectionConsistency(
209  Hrc_Manager_t *hmgr, 
210  Hrc_Model_t *model, 
211  Hrc_Node_t *hnode, 
212  array_t *subcktArray)
213{
214  int i, j;
215  IoSubckt_t *subckt;
216  char *nameOfSubcktModel, *instanceName, *formalName, *actualName, *actualPort;
217  Hrc_Model_t *subcktModel;
218  Hrc_Node_t *subcktHnode;
219  st_table *tmpTable;
220  st_table *outputCheckTable;
221  array_t *formalNameArray, *actualNameArray, *actualInputArray, *actualOutputArray;
222  Var_Variable_t *port, *var;
223
224  for (i=0; i < array_n(subcktArray); i++){
225    subckt = array_fetch(IoSubckt_t *,subcktArray,i);
226    nameOfSubcktModel = subckt->modelName;
227    if ((subcktModel = Hrc_ManagerFindModelByName(hmgr,nameOfSubcktModel)) == NIL(Hrc_Model_t)){
228      error_append("Error: Model ");
229      error_append(Hrc_ModelReadName(model));
230      error_append(" has a subcircuit whose model ");
231      error_append(nameOfSubcktModel);
232      error_append(" is not defined.\n");
233      return 0;
234    }
235
236    subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
237    instanceName = subckt->instanceName;
238    formalNameArray = subckt->formalNameArray;
239    actualNameArray = subckt->actualNameArray;
240    assert(array_n(formalNameArray) == array_n(actualNameArray));
241
242    if (array_n(formalNameArray) != 
243        Hrc_NodeReadNumFormalInputs(subcktHnode) + Hrc_NodeReadNumFormalOutputs(subcktHnode)){
244      error_append("Error: Subcircuit ");
245      error_append(instanceName);
246      error_append(" in model ");
247      error_append(Hrc_ModelReadName(model));
248      error_append(" and the corresponding model ");
249      error_append(nameOfSubcktModel);
250      error_append(" have different number of i/o ports.\n");
251      return 0;
252    }
253
254    /* creating a temporary hash table from formal names to actual names */
255    tmpTable = st_init_table(strcmp,st_strhash);
256    for (j=0; j < array_n(formalNameArray); j++){
257      formalName = array_fetch(char *,formalNameArray,j);
258      actualName = array_fetch(char *,actualNameArray,j);
259      if (st_insert(tmpTable,(char *)formalName,(char *)actualName)){
260        error_append("Error: In subcircuit ");
261        error_append(instanceName);
262        error_append(" in model ");
263        error_append(Hrc_ModelReadName(model));
264        error_append(", formal variable ");
265        error_append(formalName);
266        error_append(" is used more than once.\n");
267        st_free_table(tmpTable);
268        return 0;
269      }
270    }
271
272    /* create actualInputArray */
273    actualInputArray = array_alloc(Var_Variable_t *,0);
274    actualOutputArray = array_alloc(Var_Variable_t *,0);
275    Hrc_NodeForEachFormalInput(subcktHnode,j,port){
276      if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
277        error_append("Error: Subcircuit ");
278        error_append(instanceName);
279        error_append(" in model ");
280        error_append(Hrc_ModelReadName(model));
281        error_append(" has no actual variable defined for variable ");
282        error_append(Var_VariableReadName(port));
283        error_append(".\n");
284        return 0;
285      }
286      /* var should get a non-nil pointer */
287      var = Hrc_NodeFindVariableByName(hnode,actualPort);
288      if (Var_VariablesTestHaveSameDomain(var,port) == 0){
289        error_append("Error: Formal variable ");
290        error_append(Var_VariableReadName(port));
291        error_append(" and actual variable ");
292        error_append(actualPort);
293        error_append(" have different types in subcircuit ");
294        error_append(instanceName);
295        error_append(" in model ");
296        error_append(Hrc_ModelReadName(model));
297        error_append(".\n");
298        return 0;
299      }
300      if (Var_VariableSetSI(var) == -1){
301        return 0;
302      };
303      array_insert_last(Var_Variable_t *,actualInputArray,var); 
304    }
305
306    /* create actualOutputArray */
307    outputCheckTable = st_init_table(strcmp,st_strhash);
308    Hrc_NodeForEachFormalOutput(subcktHnode,j,port){
309
310      if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
311        error_append("Error: Subcircuit ");
312        error_append(instanceName);
313        error_append(" in model ");
314        error_append(Hrc_ModelReadName(model));
315        error_append(" has no actual variable defined for variable ");
316        error_append(Var_VariableReadName(port));
317        error_append(".\n");
318        return 0;
319      }
320      if (st_is_member(outputCheckTable,actualPort) == 1){
321        error_append("Error: Subcircuit ");
322        error_append(instanceName);
323        error_append(" in model ");
324        error_append(Hrc_ModelReadName(model));
325        error_append(" has more than one output connected to the same variable ");
326        error_append(actualPort);
327        error_append(".\n");
328        return 0;
329      }
330      (void)st_insert(outputCheckTable,actualPort,(char *)0);
331      /* var should get a non-nil pointer */
332      var = Hrc_NodeFindVariableByName(hnode,actualPort);
333      if (Var_VariablesTestHaveSameDomain(var,port) == 0){
334        error_append("Error: Formal variable ");
335        error_append(Var_VariableReadName(port));
336        error_append(" and actual variable ");
337        error_append(actualPort);
338        error_append(" have different types in subcircuit ");
339        error_append(instanceName);
340        error_append(" in model ");
341        error_append(Hrc_ModelReadName(model));
342        error_append(".\n");
343        return 0;
344      }
345      if (Var_VariableSetSO(var) == -1){
346        return 0;
347      };
348      array_insert_last(Var_Variable_t *,actualOutputArray,var); 
349    }
350    st_free_table(outputCheckTable);
351    st_free_table(tmpTable);
352    if (Hrc_ModelAddSubckt(model,subcktModel,instanceName,actualInputArray,actualOutputArray) == 0){
353      error_append("Error: Model ");
354      error_append(Hrc_ModelReadName(model));
355      error_append(" has two subcircuits with the same instance name ");
356      error_append(instanceName);
357      error_append("\n");
358      return 0;
359    }
360  }
361  return 1;
362}
363
364
365/**Function********************************************************************
366
367  Synopsis    [Checks to see if there is no inconsistency in a latch definition.]
368
369  Description []
370
371  SideEffects []
372
373  SeeAlso     []
374
375******************************************************************************/
376static boolean
377_IoModelTestLatchConsistency(Hrc_Node_t *hnode)
378{
379  Hrc_Latch_t *latch;
380  Var_Variable_t *varIn, *varOut;
381  st_generator *gen;
382  char *latchName;
383
384  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
385    varIn = Hrc_LatchReadInput(latch);
386    varOut = Hrc_LatchReadOutput(latch);
387    if (Var_VariablesTestHaveSameDomain(varIn,varOut) == 0){
388      error_append("Error: The input and the output of latch ");
389      error_append(latchName);
390      error_append(" have different domains.\n"); 
391      return 0; 
392    }
393    if (Hrc_LatchReadResetTable(latch) == NIL(Tbl_Table_t)){
394      error_append("Error: Latch ");
395      error_append(Var_VariableReadName(varOut));
396      error_append(" has no reset table.\n");
397      return 0;
398    }
399  }
400  return 1;
401}
402
403/**Function********************************************************************
404
405  Synopsis    [Checks to see if there is no inconsistency in reset declarations.]
406
407  Description []
408
409  SideEffects []
410
411  SeeAlso     []
412
413******************************************************************************/
414
415static boolean
416_IoModelTestResetConsistency(
417  Hrc_Manager_t *hmgr,
418  Hrc_Model_t *model,
419  Hrc_Node_t *hnode,
420  array_t *resetArray)
421{
422  int i;
423  Var_Variable_t *output;
424  Tbl_Table_t *resetTable;
425  Hrc_Latch_t *latch;
426
427  for (i=0; i < array_n(resetArray); i++){
428    resetTable = array_fetch(Tbl_Table_t *,resetArray,i);
429    if (Tbl_TableReadNumOutputs(resetTable) != 1){
430      error_append("Error: Reset table with output ");
431      error_append(Var_VariableReadName(Tbl_TableReadIndexVar(resetTable,0,1)));
432      error_append(" has to be a single output table.\n");
433      return 0;
434    }
435    output = Tbl_TableReadIndexVar(resetTable,0,1);
436    if (Var_VariableTestIsPS(output) == 0){
437      error_append("Error: Reset table with output ");
438      error_append(Var_VariableReadName(output));
439      error_append(" is not attached to a latch.\n");
440      return 0;
441    }
442    latch = Hrc_NodeFindLatchByName(hnode,Var_VariableReadName(output));
443    if (Hrc_LatchSetResetTable(latch,resetTable) == 0){
444      error_append("Error: You try to overwrite the reset table of ");
445      error_append(Var_VariableReadName(output));
446      error_append(".\n");
447      return 0;
448    }
449    /* once a reset table is associated with a latch,
450    we remove the table from resetArray */
451    array_insert(Tbl_Table_t *,resetArray,i,NIL(Tbl_Table_t));
452  }
453  return 1;
454}
455
456
457/**Function********************************************************************
458
459  Synopsis    [Checks the consistency of the internal connection of a model.]
460
461  Description [Checks the consistency of the internal connection of a model.
462  Returns 1 if success. Otherwise returns 0.]
463
464  SideEffects []
465
466  SeeAlso     []
467
468******************************************************************************/
469static boolean
470_IoModelTestInternalConnectionConsistency(
471  Hrc_Model_t *model,
472  Hrc_Node_t *hnode,
473  boolean isVerbose)
474{
475  st_table *varToTable, *outputVarToSubckt, *inputVarToSubckt, *visitTable;
476  st_generator *gen;
477  int i, j, status, warningStatus;
478  Var_Variable_t *var, *actualOutput;
479  Tbl_Table_t *table;
480  char *varName, *subcktName, *latchName;
481  Hrc_Subckt_t *subckt, *anotherSubckt;
482  Hrc_Latch_t *latch;
483 
484  /* creates a hash table from variables to tables */ 
485  varToTable = st_init_table(st_ptrcmp,st_ptrhash);
486  Hrc_NodeForEachNameTable(hnode,i,table){
487    Tbl_TableForEachOutputVar(table,j,var){
488      if (Var_VariableTestIsPI(var) == 1){
489        error_append("Error: Primary input ");
490        error_append(Var_VariableReadName(var));
491        error_append(" is an output of a table in model ");
492        error_append(Hrc_ModelReadName(model));
493        error_append(".\n");
494        st_free_table(varToTable);
495        return 0; 
496      }
497      if (st_insert(varToTable,(char *)var,(char *)table) == 1){
498        error_append("Error: Variable ");
499        error_append(Var_VariableReadName(var));
500        error_append(" is an output of more than one table in model ");
501        error_append(Hrc_ModelReadName(model));
502        error_append(".\n");
503        st_free_table(varToTable);
504        return 0;
505      }
506    }
507  }
508  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
509    if (st_insert(varToTable,(char *)Hrc_LatchReadOutput(latch),(char *)Hrc_LatchReadResetTable(latch)) == 1){
510      error_append("Error: Latch output ");
511      error_append(Var_VariableReadName(Hrc_LatchReadOutput(latch)));
512      error_append(" is an output of a table in model ");
513      error_append(Hrc_ModelReadName(model));
514      error_append(".\n");
515      st_free_table(varToTable);
516      return 0;
517    }
518  }
519
520  /* creates two hash tables
521     one from output variables of subckts to subckts
522     the other one from input variables of subckts to subckts */
523  outputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
524  inputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
525
526  Hrc_ModelForEachSubckt(model,gen,subcktName,subckt){
527    array_t *actualOutputs = Hrc_SubcktReadActualOutputVars(subckt);
528    array_t *actualInputs = Hrc_SubcktReadActualInputVars(subckt);
529
530    for (i=0; i < array_n(actualOutputs); i++){
531      actualOutput = array_fetch(Var_Variable_t *,actualOutputs,i);
532      if (st_lookup(varToTable,(char *)actualOutput,&table) == 1){
533        error_append("Error: Subckt output ");
534        error_append(Var_VariableReadName(actualOutput));
535        error_append(" in ");
536        error_append(subcktName);
537        error_append(" is an output of a table in model ");
538        error_append(Hrc_ModelReadName(model));
539        error_append(".\n");
540        st_free_table(varToTable);
541        st_free_table(outputVarToSubckt);
542        st_free_gen(gen);
543        return 0;
544      }
545      if (st_lookup(outputVarToSubckt,(char *)actualOutput,&anotherSubckt) == 1){
546        error_append("Error: Subckt output ");
547        error_append(Var_VariableReadName(actualOutput));
548        error_append(" in ");
549        error_append(subcktName);
550        error_append(" is also a subckt output of ");
551        error_append(Hrc_SubcktReadInstanceName(anotherSubckt));
552        error_append(" in model ");
553        error_append(Hrc_ModelReadName(model));
554        error_append(".\n");
555        st_free_table(varToTable);
556        st_free_table(outputVarToSubckt);
557        st_free_gen(gen);
558        return 0;
559      }
560      (void)st_insert(outputVarToSubckt,(char *)actualOutput,(char *)subckt);
561    }
562   
563    for (i=0; i < array_n(actualInputs); i++){
564      Var_Variable_t *actualInput = array_fetch(Var_Variable_t *,actualInputs,i);
565      (void)st_insert(inputVarToSubckt,(char *)actualInput,(char *)subckt);
566    }
567
568  }
569
570  /* start checking the consistency of a hnode */
571  Hrc_NodeForEachVariable(hnode,gen,varName,var) {
572    if (st_lookup(varToTable,(char *)var,&table) == 0){
573      if (Var_VariableTestIsPS(var) == 1 || Var_VariableTestIsPI(var) == 1){
574        continue;
575      }
576      else {
577       if (st_lookup(outputVarToSubckt,(char *)var,&subckt) == 0) { 
578         error_append("Error: Variable "); 
579         error_append(varName); 
580         error_append(" is not defined as an output of a table in model "); 
581         error_append(Hrc_ModelReadName(model)); 
582         error_append(".\n"); 
583         st_free_table(varToTable); 
584         st_free_gen(gen); 
585         return 0; 
586       }
587    }
588    }
589  }
590
591 
592  /* compute numFanoutTables */
593  Hrc_NodeForEachNameTable(hnode,i,table){
594    Tbl_TableForEachInputVar(table,j,var){
595      Var_VariableIncrementNumFanoutTables(var);
596    }
597  }
598
599  /* acyclic check */
600  visitTable = st_init_table(st_ptrcmp,st_ptrhash);
601  status = _IoModelTestIsAcyclic(model,hnode,varToTable,outputVarToSubckt,visitTable);
602  warningStatus = 0;
603  if (status == 1){
604  /* as a by-product of the acyclic check, visitTable now contains
605  all the variables reachable from either PO, NS, or reset tables.
606  We use this to detect all the variables not used in the hnode */
607    Hrc_NodeForEachVariable(hnode,gen,varName,var){
608      if (st_is_member(visitTable,(char *)var) == 0 && 
609          st_is_member(inputVarToSubckt,(char *)var) == 0 &&
610          Var_VariableTestIsPO(var) == 0 &&
611          Var_VariableTestIsNS(var) == 0 &&
612          Var_VariableTestIsPS(var) == 0 ){
613        warningStatus = 1;
614        if (isVerbose){
615          /* the following is just a warning. We do not return a failure status */
616          error_append("Warning: Variable ");
617          error_append(Var_VariableReadName(var));
618          error_append(" is not used in ");
619          error_append(Hrc_ModelReadName(model));
620          error_append(".\n");
621        }
622      }
623    }
624  }
625  if (isVerbose == 0 && warningStatus == 1){
626    error_append("Warning: Some variables are unused in model ");
627    error_append(Hrc_ModelReadName(model));
628    error_append(".\n");
629  }
630  st_free_table(varToTable);
631  st_free_table(outputVarToSubckt);
632  st_free_table(inputVarToSubckt);
633  st_free_table(visitTable);
634
635  return 1;
636}
637
638
639/**Function********************************************************************
640
641  Synopsis    [A DFS-based procedure for checking acyclicity.]
642
643  Description []
644
645  SideEffects []
646
647  SeeAlso     []
648
649******************************************************************************/
650static boolean
651_IoModelTestIsAcyclic(
652  Hrc_Model_t *model,
653  Hrc_Node_t *hnode,
654  st_table *varToTable,
655  st_table *outputVarToSubckt,
656  st_table *visitTable)
657{
658  int i;
659  Var_Variable_t *var;
660  st_generator *gen;
661  char *latchName;
662  Hrc_Latch_t *latch;
663
664  Hrc_NodeForEachFormalOutput(hnode,i,var){
665    if (_IoModelTestIsAcyclicRecursive(model,hnode,var,varToTable,outputVarToSubckt,visitTable,0) == 0){
666      _IoModelTestIsAcyclicError(model,var);
667      return 0;
668    }
669  }
670  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
671    Tbl_Table_t *resetTable;
672
673    resetTable = Hrc_LatchReadResetTable(latch);
674    Tbl_TableForEachInputVar(resetTable,i,var){
675      int status;
676      if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,
677          var,varToTable,outputVarToSubckt,visitTable,1)) == 0){
678        _IoModelTestIsAcyclicError(model,var);
679        st_free_gen(gen);
680        return 0;
681      }
682      /* found a path from a PS to a reset table */
683      if (status == -1){
684        error_append(latchName);
685        error_append(" in model ");
686        error_append(Hrc_ModelReadName(model));
687        error_append(".\n");
688        st_free_gen(gen);
689        return 0;
690      }
691    } 
692  }
693  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
694    if (_IoModelTestIsAcyclicRecursive(model,hnode,
695        (var = Hrc_LatchReadInput(latch)),varToTable,outputVarToSubckt,visitTable,0) == 0){
696      _IoModelTestIsAcyclicError(model,var);
697      st_free_gen(gen);
698      return 0;
699    } 
700  }
701  return 1;
702}
703
704/**Function********************************************************************
705
706  Synopsis    [Prints out error messages during an acyclic check.]
707
708  Description []
709
710  SideEffects []
711
712  SeeAlso     []
713
714******************************************************************************/
715static void
716_IoModelTestIsAcyclicError(
717  Hrc_Model_t *model,
718  Var_Variable_t *var)
719{
720  error_append("Warning: Model ");
721  error_append(Hrc_ModelReadName(model));
722  error_append(" may have a cyclic connection which involves variable ");
723  error_append(Var_VariableReadName(var));
724  error_append("\n");
725}
726
727/**Function********************************************************************
728
729  Synopsis    [Recursive DFS routine for acyclic check.]
730
731  Description []
732
733  SideEffects []
734
735  SeeAlso     []
736
737******************************************************************************/
738static int
739_IoModelTestIsAcyclicRecursive(
740  Hrc_Model_t *model,
741  Hrc_Node_t *hnode,
742  Var_Variable_t *var,
743  st_table *varToTable,
744  st_table *outputVarToSubckt,
745  st_table *visitTable,
746  boolean isResetLogic)
747{
748  int val, i;
749  Var_Variable_t *input;
750  Tbl_Table_t *table;
751  Hrc_Subckt_t *subckt;
752
753  if (st_lookup_int(visitTable,(char *)var, &val) == 1){
754    return (!val);
755  }
756  else{
757    (void)st_insert(visitTable,(char *)var,(char *)1);
758   
759    if (Var_VariableTestIsPI(var) == 0 &&
760           (isResetLogic || Var_VariableTestIsPS(var) == 0)){
761      if (isResetLogic && (Var_VariableTestIsPS(var) == 1)){
762        error_append("Warning: There is a path from latch output ");
763        error_append(Var_VariableReadName(var));
764        error_append(" to reset table ");
765
766        /* the error message is to be continued in _IoModelTestIsAcyclic() */
767        return -1; 
768      }
769      if (st_lookup(varToTable,(char *)var,&table) == 1){
770        Tbl_TableForEachInputVar(table,i,input){
771          int status;
772          if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
773                           varToTable,outputVarToSubckt,visitTable,isResetLogic)) == 0){
774            return 0;
775          }
776          if (status == -1){
777            return -1;
778          }
779        }
780      }
781      else {
782        array_t *actualInputs;
783        /* the return value of the following st_lookup should be 1 */
784        (void)st_lookup(outputVarToSubckt,(char *)var,&subckt);
785        actualInputs = Hrc_SubcktReadActualInputVars(subckt);
786        assert (actualInputs != NIL(array_t));
787        for (i=0; i < array_n(actualInputs); i++){
788          int status;
789          input = array_fetch(Var_Variable_t *,actualInputs,i);
790          if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
791                         varToTable,outputVarToSubckt,visitTable,0)) == 0){
792            return 0;
793          }
794          if (status == -1){
795            return -1;
796          }
797        }
798      }
799    }
800    (void)st_insert(visitTable,(char *)var,(char *)0);
801    return 1;
802  }
803}
804
805
806
807
808
809
810
811
812
813
814
815
816
817
Note: See TracBrowser for help on using the repository browser.