/**CFile*********************************************************************** FileName [ioReadBlifMv.c] PackageName [io] Synopsis [Routines related to reading in blif-mv files.] Description [] SeeAlso [] Author [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang] 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.] ******************************************************************************/ #include "ioInt.h" static char rcsid[] UNUSED = "$Id: ioReadBlifMv.c,v 1.12 2002/09/10 04:35:24 fabio Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #ifndef NAWK #define NAWK "gawk" #endif /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ static jmp_buf env; extern FILE *IoYyin; extern int globalCurrentStackDepth; #ifdef IODEBUG extern int IoYydebug; #endif /*IODEBUG */ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void _IoGlobalVariablesInitialize(void); static void _IoGlobalVariablesFree(void); static void _IoGlobalSubcktInfoFree(void); static void _IoSubcktArrayFree(array_t *array); static void _IoSubcktFree(IoSubckt_t *subckt); static void _IoGlobalResetInfoFree(void); static boolean _IoNodeTestCompatibilityAux(Hrc_Manager_t *hmgr, Hrc_Node_t *hnode1, Hrc_Node_t *hnode2, boolean mode); static void _IoManagerCanonicalize(Hrc_Manager_t *hmgr); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reads in a blif-mv file.] Description [Reads in a blif-mv file. Returns a pointer to a new hierarchy manager if isIncremental == 0. If isIncremental == 1, hmgr should be set to the current manager and will be updated by this function call. If isCanonical == 1, then all the tables in each model will be canonicalized with Tbl_TableCanonicalize(). If isVerbose == 1, all the unused variables are listed for each model while if isVerbose == 0, all the models that have an unused variable are simply listed. These messages can be referred to by error_string() after the call. Returns NIL(Hrc_Manager_t) if failure.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Manager_t * Io_BlifMvRead( FILE *fp, Hrc_Manager_t *hmgr, boolean isCanonical, boolean isIncremental, boolean isVerbose) { Hrc_Node_t *root; static Hrc_Manager_t *newHmgr; if (isIncremental == 0){ newHmgr = Hrc_ManagerAlloc(); } else { /* isIncremental == 1 */ if (Hrc_ManagerReadCurrentNode(hmgr) == NIL(Hrc_Node_t)){ (void)fprintf(vis_stderr,"No hierarchy has been created. Cannot do inremental read-in.\n"); return NIL(Hrc_Manager_t); } newHmgr = hmgr; } if (setjmp(env)){ if (isIncremental == 0){ Hrc_ManagerFree(newHmgr); } else { int i; /* free all the new models defined in an incremental file */ for (i=0; i < array_n(globalNewModelArray); i++){ Hrc_ModelDelete(hmgr,Hrc_ModelReadName(array_fetch(Hrc_Model_t *,globalNewModelArray,i))); } } _IoGlobalVariablesFree(); return NIL(Hrc_Manager_t); } else { _IoGlobalVariablesInitialize(); if (isIncremental == 0){ globalYaccHmgr = newHmgr; } else { globalYaccHmgr = hmgr; } #ifdef IODEBUG IoYydebug = 1; #endif /* IODEBUG */ IoYyin = fp; IoYyrestart(IoYyin); if (IoYyparse() == 1){ IoError(); } /* globalNewModelArray contains all the models defined in the previous IoYyparse(). If isIncremental==0, then they are simply all the models. If isIncremental==1, then they are new models defined in the file. */ if (IoNetworkTestConsistency(newHmgr,globalNewModelArray,globalParserSubcktInfo,globalParserResetInfo,isVerbose) == 0){ IoError(); } if (globalRootModel == NIL(Hrc_Model_t)){ globalRootModel = globalFirstModel; globalRootInstanceName = util_strsav(Hrc_ModelReadName(globalRootModel)); } else if (globalRootInstanceName == NIL(char)){ globalRootInstanceName = util_strsav(Hrc_ModelReadName(globalRootModel)); } if (isCanonical == 1){ _IoManagerCanonicalize(newHmgr); } root = Hrc_ModelCreateHierarchy(newHmgr,globalRootModel,globalRootInstanceName); FREE(globalRootInstanceName); if (isIncremental == 0){ Hrc_ManagerSetRootNode(newHmgr,root); Hrc_ManagerSetCurrentNode(newHmgr,root); _IoGlobalVariablesFree(); return newHmgr; } else { /* isIncremental == 1, note that newHmgr == hmgr */ if (_IoNodeTestCompatibility(hmgr,Hrc_ManagerReadCurrentNode(hmgr),root) == 0){ int i; (void)fprintf(vis_stderr,"The blif-mv file is not compatible with the existing hierarchy.\n"); Hrc_TreeReplace(NIL(Hrc_Node_t),root); /* free all the new models defined in an incremental file */ for (i=0; i < array_n(globalNewModelArray); i++){ Hrc_ModelDelete(hmgr,Hrc_ModelReadName(array_fetch(Hrc_Model_t *,globalNewModelArray,i))); } _IoGlobalVariablesFree(); return NIL(Hrc_Manager_t); } Hrc_TreeReplace(Hrc_ManagerReadCurrentNode(hmgr),root); Hrc_ManagerSetCurrentNode(hmgr,root); _IoGlobalVariablesFree(); return hmgr; } } } /**Function******************************************************************** Synopsis [Reads in a blif file.] Description [Reads in a blif file specified by its file name. Returns a pointer to a new hierarchy manager. All the error/warning messages obtained while parsing the file are stored in error_string(). isVerbose should be set either to one or to zero depending on how much detailed error/warning information is needed. Returns NIL(Hrc_Manager_t) if failure.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Manager_t * Io_BlifRead( char *fileName, boolean isVerbose) { FILE *fp; #if HAVE_MKSTEMP && HAVE_CLOSE int fd; #else char buffer[512]; #endif char *realFileName, *blifMvFileName, *visDirectoryName; char command[512]; Hrc_Manager_t *hmgr; fp = Cmd_FileOpen(fileName, "r", &realFileName, /* silent */ 1); if (fp == NIL(FILE)){ FREE(realFileName); (void)fprintf(vis_stderr,"File %s is not found.\n", fileName); return NIL(Hrc_Manager_t); } if (fp != stdin){ (void)fclose(fp); } #if HAVE_MKSTEMP && HAVE_CLOSE blifMvFileName = util_strsav("/tmp/vis.XXXXXX"); fd = mkstemp(blifMvFileName); if (fd == -1){ #else blifMvFileName = util_strsav(tmpnam(buffer)); if (blifMvFileName == NIL(char)){ #endif FREE(realFileName); (void)fprintf(vis_stderr,"Could not create temporary file. "); (void)fprintf(vis_stderr,"Clean up /tmp an try again.\n"); return NIL(Hrc_Manager_t); } #if HAVE_MKSTEMP && HAVE_CLOSE close(fd); #endif /* Invoking an awk script */ visDirectoryName = Vm_VisObtainLibrary(); (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{//g'| sed 's/(/<>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName); /* the following is missing two new sed processings (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{//g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName); */ (void)system(command); FREE(visDirectoryName); FREE(realFileName); error_init(); fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1); assert(fp != NIL(FILE)); hmgr = Io_BlifMvRead(fp,NIL(Hrc_Manager_t),0,0,isVerbose); fclose(fp); #if HAVE_UNLINK unlink(blifMvFileName); #endif FREE(blifMvFileName); return hmgr; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Jumps out of an error state.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void IoError(void) { longjmp(env,1); } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initilizes all the global variables used in the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoGlobalVariablesInitialize(void) { globalLineNumber = 1; globalModel = NIL(Hrc_Model_t); globalHnode = NIL(Hrc_Node_t); globalFirstModel = NIL(Hrc_Model_t); /* set once */ globalRootModel = NIL(Hrc_Model_t); /* set once */ globalRootInstanceName = NIL(char); /* set once */ globalMvNameArray = NIL(array_t); globalSymValueArray = NIL(array_t); globalTableInputArray = NIL(array_t); globalTableOutputArray = NIL(array_t); globalTableDefaultArray = NIL(array_t); globalTableSymCubeArray = NIL(array_t); globalFormalNameArray = NIL(array_t); globalActualNameArray = NIL(array_t); globalSubcktArray = NIL(array_t); globalResetArray = NIL(array_t); globalNewModelArray = array_alloc(Hrc_Model_t *,0); globalCurrentStackDepth = 0; /* a hash table from a model name to an array of resets/subcircuits in the model */ globalParserResetInfo = st_init_table(st_ptrcmp,st_ptrhash); globalParserSubcktInfo = st_init_table(st_ptrcmp,st_ptrhash); } /**Function******************************************************************** Synopsis [Frees all the global data structures used in the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoGlobalVariablesFree(void) { array_free(globalNewModelArray); _IoGlobalResetInfoFree(); _IoGlobalSubcktInfoFree(); } /**Function******************************************************************** Synopsis [Frees the subckt information only used by the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoGlobalSubcktInfoFree(void) { st_generator *gen; char *key, *val; st_foreach_item(globalParserSubcktInfo,gen,&key,&val){ if ((array_t *)val != NIL(array_t)){ _IoSubcktArrayFree((array_t *)val); } } st_free_table(globalParserSubcktInfo); } /**Function******************************************************************** Synopsis [Frees an array of the subckt data structure only used by the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoSubcktArrayFree(array_t *array) { int i; for (i=0; i < array_n(array); i++){ _IoSubcktFree(array_fetch(IoSubckt_t *,array,i)); } array_free(array); } /**Function******************************************************************** Synopsis [Frees the subckt data structure used by the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoSubcktFree(IoSubckt_t *subckt) { FREE(subckt->modelName); FREE(subckt->instanceName); IoStringArrayFree(subckt->formalNameArray); IoStringArrayFree(subckt->actualNameArray); FREE(subckt); } /**Function******************************************************************** Synopsis [Frees the reset data structure used only by the parser.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoGlobalResetInfoFree(void) { st_generator *gen; char *key, *val; int i; Tbl_Table_t *resetTable; st_foreach_item(globalParserResetInfo,gen,&key,&val){ if ((array_t *)val != NIL(array_t)){ for (i=0; i < array_n((array_t *)val); i++){ resetTable = array_fetch(Tbl_Table_t *,(array_t *)val,i); if (resetTable != NIL(Tbl_Table_t)){ Tbl_TableFree(resetTable); } } array_free((array_t *)val); } } st_free_table(globalParserResetInfo); } /**Function******************************************************************** Synopsis [Checks if two hnodes are compatible with respect to their i/o interface.] Description [Checks if two hnodes are compatible with respect to their i/o interface. Used in incremental read-in.] SideEffects [] SeeAlso [_IoNodeTestCompatibilityAux] ******************************************************************************/ boolean _IoNodeTestCompatibility( Hrc_Manager_t *hmgr, Hrc_Node_t *hnode1, Hrc_Node_t *hnode2) { return (_IoNodeTestCompatibilityAux(hmgr,hnode1,hnode2,0) && _IoNodeTestCompatibilityAux(hmgr,hnode1,hnode2,1)); } /**Function******************************************************************** Synopsis [Checks if two hnodes are compatible with respect to their input or output interface depending on the last boolean flag.] Description [Checks if two hnodes are compatible with respect to their input or output interface depending on the last boolean flag. 0 for input and 1 for output.] SideEffects [] SeeAlso [] ******************************************************************************/ static boolean _IoNodeTestCompatibilityAux( Hrc_Manager_t *hmgr, Hrc_Node_t *hnode1, Hrc_Node_t *hnode2, boolean mode) { int i, n; array_t *formalVars1, *formalVars2; Var_Variable_t *var1, *var2; if (mode == 0){ formalVars1 = Hrc_NodeReadFormalInputs(hnode1); formalVars2 = Hrc_NodeReadFormalInputs(hnode2); } else { formalVars1 = Hrc_NodeReadFormalOutputs(hnode1); formalVars2 = Hrc_NodeReadFormalOutputs(hnode2); } if ((n = array_n(formalVars1)) != array_n(formalVars2)){ error_append("Two hnodes have different number of formal "); if (mode == 0){ error_append("inputs.\n"); } else { error_append("outputs.\n"); } return 0; } for (i=0; i < n; i++){ var1 = array_fetch(Var_Variable_t *,formalVars1,i); var2 = array_fetch(Var_Variable_t *,formalVars2,i); if (strcmp(Var_VariableReadName(var1),Var_VariableReadName(var2)) != 0){ error_append("Two hnodes have different ports, "); error_append(Var_VariableReadName(var1)); error_append(" and "); error_append(Var_VariableReadName(var2)); error_append("\n"); return 0; } if (Var_VariablesTestHaveSameDomain(var1,var2) == 0){ error_append("Two hnodes have ports defined over different domains, "); error_append(Var_VariableReadName(var1)); error_append(" and "); error_append(Var_VariableReadName(var2)); error_append("\n"); return 0; } } return 1; } /**Function******************************************************************** Synopsis [Canonicalizes all the tables in a given manager using Tbl_TableCanonicalize().] SideEffects [The original tables will be overwritten.] SeeAlso [] ******************************************************************************/ static void _IoManagerCanonicalize( Hrc_Manager_t *hmgr) { int i; Hrc_Model_t *model; Hrc_Node_t *node; Tbl_Table_t *table; st_generator *gen, *gen2; char *modelName, *latchName; Hrc_Latch_t *latch; Hrc_ManagerForEachModel(hmgr,gen,modelName,model){ node = Hrc_ModelReadMasterNode(model); Hrc_NodeForEachNameTable(node,i,table){ Tbl_TableCanonicalize(table); } Hrc_NodeForEachLatch(node,gen2,latchName,latch){ Tbl_TableCanonicalize(Hrc_LatchReadResetTable(latch)); } } }