eval '(exit $?0)' && eval 'exec perl5 -S $0 ${1+"$@"}'
& eval 'exec perl5 -S $0 $argv:q'
  if 0;

####################################################################
# HS2: HierarchySurfer2: The next (de)generation!
#  
#
#  Sorry to be restrictive, but Synopsys paid for my time to due this
#  so I strongly feel that this program should be for the benefit of 
#  Synopsys customers alone.
#
#  Copyright and Legal stuff:
#  --------------------------
#  Point 1) HS2 is copyrighted by Erik Olson and it is provided 
#           on an as is basis with no expressed nor implied warrenties.
#           You may modify and fix this code as long as this copyright 
#           information is retained unmodified AND the enhancements are
#           put into the public domain.
#
#  Point 2) Because Synopsys paid for Erik's time in creating this software,
#           use of HS2 by EDA vendors who compete with Synopsys is expressly
#           forbidden!  This includes, but is not limited to, Cadence, Mentor
#           Magma, Monterey, Get2chip, Avant!.
#
#  Point 3) You must own at least one Synopsys tool to use this software.
#           Non-commericial education uses are excepted.  This means you
#           are forbidden from using HS2 in purely Cadence flow for example.
#
#  Last point:
#  -----------
#  This is *unsupported* code.  Erik fixes this when he feels like it or
#  is bribed with US bills ending in '0'.  You can send your testcases, but
#  Erik may or may not decide to fix them.  Also, if you find and fix a bug,
#  please feel free to send the fix to Erik, so that he can claim credit for it!
#
# REVISION(ist) HISTORY:
#
# Rev 2.26: 3/1/99 DS2 enhancement
#   - Created a file that lists all the .shf files that were created
#     This is mostly to make DS2 easier to use.
#
# Rev 2.25: 12/2/98 Yet another bug from the DEC testcase
#   - Modified the magic_token list in LFMVT2 to include '=' and '<='
#     These are now 'bled' out (not parses after detection)
#     The bug is subtle and worthy of note.  In PV, the parser doesn't know if it is
#     in an always or initial block, only whether it is in a module.  Since the '`' token
#     is a magic verilog token, LFMVT2 finds it within a block and confuses PV.
#
#     I should really add (always|initial) block detection...
#
# Rev 2.24: 11/23/98 More work on fixing VHDL entity name case issues.
#   - Modified the pwd command for MSWin32 detection in set_up_HS2
#   - added global instanceName2instanceTrueName
#   - modified make_ordered_elist and make_unit_report to reflect case changes
#   - Fixed a bug in cell/reference reporting of make_ordered_elists SHF.
#
# Rev 2.23: 11/3/98 Work on fixing VHDL entity name case issues and the extra packages issues.
#   - Put a bunch of fixes in for case correct in VHDL in subs make_ordered_E_lists and make_new_VHDL_unit_report
#   - Added a new sub make_new_VHDL_unit_report, removed the old one.
#   - Fixed the VHDL issue regarding extra packages being reported
#   - Changed the banner a wee bit
#   - Changed clean_files routine for WinDOeSN'T port
#
# Rev 2.22: 9/1/98 Adding Erich's library cell feature
#   - Added the '-c' option to point to one or more files containing library cells
#     These library cells are used in parse_Verilog so these instance don't show up as 
#     'bad' or 'source not found' any more.  The library cells are just whitespace separated
#     in the file.
#   - Added the subroutine read_cell_libraries, the cells are stored in libraryCellArray
#   - Added '#' and '.' to the verilogKeywords array
#   - Verbose mode in VHDL land does cell reporting
#
# Rev 2.21: 8/28/98 More Verilog debugging
#   - Better detection of ';' statements
#   - Fixed a bug WRT verilog parameter pulling '(' substitution
#   - Must fix a bug where an extra ';' is tacked onto the end of the line. this happens with the usage of a `defined variable
#   - Added '[' and ']'  and ':' to the verilogKeywordsArray
#   - For some odd reason verilogKeywordsArray{[} doesn't work as expected...
#   - Added "<" and ">" as verilog keywords
#
# Rev 2.20: 8/25/98 A tad more Verilog work and merged in Verilog work by Andy S (Thanks Andy!!)
#   - Improved inline comment handling in get_next_Verilog_line and parse_verilog
#   - Made get_next_Verilog_line the exclusive Verilog file read routine.
#   - Added "'" and "&" as verilog keywords
#
# Rev 2.19: 8/17/98 Still more debugging on Verilog!
#   - Fixed shoddy handling of EOF conditions in all the ";" hunting routines and GVT
#   - Modified process_HS2_command_line to handle mistakes... mostly
#
# Rev 2.18: 7/17/98 Still more debugging on Verilog!
#   - Added 'assign' to the list of LFMVT2 tokens, now everything after this is parse and thrown
#   - Added '$' to the list of reserved Verilog tokens
#   - Fixed a bug with parse_verilog regarding filing instanceName_2_CellName by accident.
#
# Rev 2.17: 7/12/98 More debugging on Verilog!
#   - Changed the -D switch to accept a debugging token, the rest is not yet implemented
#   - Added a variable (inModule) to tell the parse when it is within a module description.
#   - Made Verilog instance hunting conditional on the new inModule variable
#   - Fix of escaped cell names and ports
#   - Work on the Verilog ` issue, added ` as a magic token and removed include as one
#     PV now hunts for ` and processs those line specially
#
# Rev 2.16: 7/8/98 Bug file to remove \" tokens from Verilog lines
#   - These escaped quotes confused get_Verilog_token
#
# Rev 2.15: 7/6/98 Added Verilog reporting of cell names for a module 
#   - Added array variable moduleName_2_moduleCellNames to hold all the
#     cell names for a module in the hierarchy.  This is needed to
#     determine uniquification in DS2
#   - Fixed a VHDL bug with respect to PE in port parsing of )); port closing statments...
#
# Rev 2.14: 7/1/98 Bug fixes in Verilog parsing
#   - Fixed the DEC bug yet again...
#
# Rev 2.13: 6/30/98 Improvements in Verilog reporting
#   - include files are put on multiple lines in the SHF output now..
#
# Rev 2.12: 6/24/98 Improvements in Verilog netlist parsing
#   - added detection of reg & wire & tri statements.  These are just parsed out now.
#   - Fixed bug in verilog dc analyze/elaborate script that was re-analzing files...
#   - Fixed bug in parse_verilog regarding reseting the module variable.  This is now
#     done after the endmodule token is found.  This helps with multi-module files
#
# Rev 2.11: 6/17/98 Verilog bug fixes
#   - added get_rest_of_Verilog_line
#
# Rev 2.10: 6/17/98 Verilog endif fix part2
#   - an `ifdef/`endif inside a port list was killing the parser.
#     The old fix was to remove endif from the end keyword list in LFMVT2
#     but this didn't work when the `endif preceeded a module instance
#     Fixed this by parsing to the end of a port list after a module is found
#   - Added parse_to_end_of_Verilog_statement sub.
#   - Fixed unknown cell's sub-design info for Verilog SHF
#
# Rev 2.09: 6/15/98 Added port and parameter parsing for Verilog
#   - Added three new global hashes
#        * verilogModule_2_input
#        * verilogModule_2_output
#        * verilogModule_2_parameter
#   - Added input, output, and parameter reporting to the SHF file
#   - Modified get_token to fix more regexp issues
#   - Fixed the -l switch to match on the needed chars and be case insensitive
#
# Rev 2.08: 6/10/98 Added port parsing for VHDL
#   - Modified parse_entity and make_ordered_Elists
#   - Added four new global hashes
#        * entity_2_input
#        * entity_2_output
#        * entity_2_buffer
#        * entity_2_inout
#   - Added port reporting to SHF extra data 
#
# Rev 2.07: 6/8/98 improved links with DS2
#   - Modified SHF output for Verilog and VHDL to allow cell highlighting
#
# Rev 2.06a: 6/4/98 Attempting to bring VHDL up to speed
#   - Added cell name detection and storage (into list variable ACell_list)
#   - Added variables 
#          master_merge_kid_cell_list and MERGE_CNList to merge 
#          ACell_list to global
#          cell_list to global
#   - Added reporting of cell names in the unit_report and SHF for VHDL
#   - Will improve the formating of the VHDL unit_reports and SHF files
#
# Rev 2.05: 6/2/98 Lots of Verilog work
#   - Improved the formating of the Verilog unit_reports and SHF files
#   - Added the (#) notation into the Verilog unit_report to show parameters.
#   - Improved the unit report to not print the missing instances line if there are none
#   - Detect and ignore "in-block" quotes, like with $display() statements.
#     This is a better fix than the one in v2.04, that is now commented out.
#   - Added cell name storage into hash variable instanceName_2_CellName stores (parent:cell|)
#   - Added parameter name storage into hash variable instanceName_2_Parmeter (parent:cell:parm|)
#   - Added reporting of cell names and parameters in the unit_report and SHF for Verilog
#   - Changed parse_verilog to report all instances and their cell names
#
# Rev 2.04: 5/29/98 Fix of Verilog endmodule problem
#   - Modified LFMVT2 to force a return of a endmodule no matter what the depth counter says
#   - Found there is a bug with depth tokens in "  " quotes
#
# Rev 2.03: 5/28/98 Fix of Verilog top module switch (-t) and DEC bug
#   - Moved forced case switch to a VHDL sub instead of process_HS2_command_line
#   - Removed 'endif' from the list of legal end tokens in LFMVT2
#   - Three tiny tweeks to pass the Perl4 syntax checker.
#
# Rev 2.02: 5/27/98 Fix of Verilog leaf cell problems in SHF
#   - Mucked with make_ordered_module_list
#   - Added a surfDir variable for the location of the surf launch
#   - Added the surfDate variable for the time/date of the surf
#
# Rev 2.01: 5/18/98 fix of 'define' problem, cut 1
#   - Added the sub get_next_Verilog_line, used in LFMVT2 and G
#
# Rev 2.0: 4/27/98 Unified HS and HSV
#   
#
####################################################################

&check_for_right_version;
&surf_the_code;

################################
#
# End of main, man, that was easy...
#
################################

sub surf_the_code {

   &set_up_HS2;
   &process_HS2_command_line;
   
   printf   "\nHierarchySurfer2 (%s)! Let's Rock!\n", $version;
   printf   "======================================================================================\n";
   printf   "| HS2 was conceived, implemented, screwed up, and mostly fixed by Erik Olson         |\n";             
   printf   "| HS2 is copyrighted by Erik Olson, but officially unsupported by Synopsys and Erik  |\n"; 
   printf   "| HS2 is intended only for Synopsys customers, see program comments for restrictions |\n";
   printf   "| Send all enhancement requests on the back of a \$100 bill!                          |\n";
   printf   "| Feedback to erik\@synopsys.com                                                      |\n";
   printf   "======================================================================================\n";
   printf   "Setting up HS2\n" if $verbose_mode;
   printf   "--------------\n" if $verbose_mode;

   if ( $targetLanguage =~ /[Vv][Ee].*/ ) {
      printf "Surfing the Verilog code\n" if $verbose_mode;
      &surf_the_verilog_code;
   } elsif ( $targetLanguage =~ /[Vv][Hh].*/ ) {
      printf "Surfing the VHDL code\n" if $verbose_mode;
      &surf_the_VHDL_code;
   } else {
      printf "Major Bummer dude, I don't know how to surf \"%s\" \n", $targetLanguage;
      exit;
   }
      
   # Clean up the mess, if desired...
   if ($removeTempFiles == 1) {
      &clean_files;
   }

   &make_shfFiles_list_file;
   &make_shell_clean_files;

   printf  "\nDone surfing, later dude!\n";   
}

sub surf_the_VHDL_code {

   ######################
   #
   # surf_the_VHDL_code
   # added v1.15
   # 
   # This does the VHDL work
   #
   ######################

   &set_up_HS;
   &deal_with_HS_startup_switches;
   &set_up_HS_data_structures ;
   &read_cell_libraries(1);
   &parse_VHDL;
   &deal_with_packages;
   &merge_VHDL;
   &build_VHDL_design_hierarchy;
   &process_VHDL_designs;
}

sub deal_with_HS_startup_switches {
   ###################################
   #
   # deal_with_HS_startup_switches
   # Added: v1.15
   #
   # This:
   # - deals with the debugging switches
   # - echos out some setup feedback
   # - finds all the sources files to parse. (source_file_list)
   #
   ####################################

   # Debugging switches, basically useless                         
   if ($global_debug == 1) {
      $GMT_tells_all = 1;
      $GT_tells_all = 1;
      $PA_tells_all = 1;
      $PV_tells_all = 1;
      $LFMVT2_tells_all = 1;
      $DC_tells_all = 1;
      $PC_tells_all = 1;
      $M_tells_all = 1;
      $PE_tells_all = 1;
      $PARSE_VHDL_tells_all = 1;
      $MOEL_tells_all = 1;
      $BDH_tells_all = 1;
      $MCPL_tells_all = 1;
      $MP_tells_all = 1;
      $BPH_tells_all = 1;
      $MOP_tells_all = 1;
      $MSimMF_tells_all = 1;
   } else {
      $GMT_tells_all = 0;
      $GT_tells_all = 0;
      $GST_tells_all = 0;
      $PA_tells_all = 0;
      $DC_tells_all = 0;
      $PC_tells_all = 0;
      $M_tells_all = 0;
      $PE_tells_all = 0;
      $PARSE_VHDL_tells_all = 0;
      $MOEL_tells_all = 0;
      $BDH_tells_all = 0;
      $MCPL_tells_all = 0;
      $MP_tells_all = 0;
      $PV_tells_all = 1;
      $PP_tells_all = 0;   
      $BPH_tells_all = 0;
      $MOP_tells_all = 0;
      $MSimMF_tells_all = 0;
   }

   # This used to be in the switch parser, but we only want this to work with VHDL, not Verilog
   $top_entity = "\U$top_entity";

   if ($top_entity eq "") {
      printf STDOUT "   No explicit top design given, therefore all parent designs will be derived\n" if $verbose_mode;
   } else {
      printf STDOUT "   Looking for root entity %s\n", $top_entity if $verbose_mode;
   }

   if ($fileExclusion != 0 ) {
      printf STDOUT "\n   The following source files are excluded from parsing:\n" if $verbose_mode;
      foreach $source_dir ( keys(%fileExclusionArray) ) {
	 printf STDOUT "      \"%s\"\n", $source_dir if $verbose_mode;
      }
   }

   printf STDOUT "\n   Looking for source files in the following directories:\n" if $verbose_mode;
   foreach $source_dir ( @source_dir_list ) {
      printf STDOUT "      \"%s\"\n", $source_dir if $verbose_mode;
   }

   printf STDOUT "\n   Looking for source files with the following extensions:\n" if $verbose_mode;
   foreach $source_ext ( @source_ext_list ) {
      printf STDOUT "      \"%s\" \n", $source_ext if $verbose_mode;
   }

   # Build the list of files to parse
   # set the list source_file_list
   #
   foreach $source_directory_path ( @source_dir_list ) {
      foreach $source_extension ( @source_ext_list ) {
         $glob_pattern = $source_directory_path . "/*." . $source_extension;
         #printf STDOUT "MAIN: source directory path $s\n", $source_directory_path;
         #printf STDOUT "MAIN: source extension $s\n", $source_extension;
         #printf STDOUT "MAIN: source file glob pattern $s\n", $glob_pattern;
         @dir_file_list = <${glob_pattern}>;
         foreach $temp_dir_file (@dir_file_list) {
            printf STDOUT "MAIN: Saving target file $s\n", $temp_dir_file if $MAIN_tells_all;
            push (@source_file_list, $temp_dir_file);
         } 
      }
   }
}

sub set_up_HS_data_structures {
   ###################################
   #
   # set_up_HS_data_structures  
   # Added: v1.15
   #
   # This sets up the debugging output files and
   # the main data structures.
   #
   ####################################

   # Create the mda (multi-D array) file
   $mda_root = ".mda_file";
   $mda =  $outputDirectory . $mda_root;
   push( @filesToKillList, $mda );
   if ( !open (MDA, ">$mda") )  {
      "HierachySurfer/SUHSDS: Can't open the file \"$mda\" for output!\n";
   }
   printf MDA "Parse (MDA) output data\n";

   # Create the mmda (merged multi-D array) file
   $mmda_root = ".mmda_file";
   $mmda =  $outputDirectory . $mmda_root;
   push( @filesToKillList, $mmda );
   if ( !open (MMDA, ">$mmda") )  {
      "HierachySurfer/SUHSDS: Can't open the file \"$mmda\" for output!\n";
   }
   printf MMDA "Merged output data\n";
   printf MMDA "Ordinal | Entity Name | True Entity Name | List of Archs | List of Congfigs | List of Files | List of Instances\n";

   # Create the mmda (merged multi-D package array) file
   $mpda_root = ".mpda_file";
   $mpda = $outputDirectory . $mpda_root;
   push( @filesToKillList, $mpda );
   if ( !open (MPDA, ">$mpda") )  {
      "HierachySurfer/SUHSDS: Can't open the file \"$mpda\" for output!\n";
   }
   printf MPDA "Merged package output data\n";
   printf MPDA "Package Name | Source Files | Declared Components | Kid Packages \n";

   # init the variables
   @entity_only = ();
   @package_only = ();
   $entity_counter = 0;
   @E_list = ();
   @A_list = ();
   @AE_list = ();
   @C_list = ();
   @CE_list = ();
   $ordinal_counter= 0;
   @uncleanEList = ();
   @uncleanAList = ();
   @uncleanFList = ();
   %entityNameToMDAOrdinal = ();
   %entityBogusNameToRealName = ();
   @totalLibraryList = ();
}

sub parse_VHDL {
   ###################################
   #
   # parse_VHDL
   # Added: v1.15
   #
   # This parses every source file in (source_file_list) into
   # the file data structure.  For each major part (ent/arch/config/package)
   # of the file, the sub save_parse_info is called to save the info.
   #
   # Main parsing section
   # After this is complete, all the source files should be parsed and
   # the extracted infomation is in the psuedo multi-D arrays.
   # Here are the used variables
   #
   #    ECA_file_list      : The name of the parsed file
   #    E_list             : The list of entity names in uppercase
   #    E_trueName_list    : The list of the entity's real names
   #    A_list             : The list of Architecture names
   #    AE_list            : The list of entity names TIED to the found Architectures
   #    C_list             : The list of configuration names
   #    CE_list            : The list of entity names TIED to the found configurations
   #    CA_list            : The list of Architectures names TIED to the found configurations
   #    AComp_list         : The list of components declared within an Architecture
   #    AInst_list         : The complete list of components instanced within an Architcture
   #    AConfig_list       : The list of configurations of given architecture
   #    P_list             : The list of Package names
   #    PB_list            : The list of Package body names
   #    entity_only        : The list of entitys (keys) to the data structure
   #
   #    sourceFile_2_packages  : List of packages in this source file 
   #    sourceFile_2_libraries : List of libraries in this source file 
   #
   ####################################

   # Make sure there are source files to play with.
   if ( @source_file_list == () ) {
      printf STDOUT "\n\n\n Sorry dude, I could not find any VHDL source files, later... \n";
      exit;
   }

   printf STDOUT "\nSurfing source files:\n" if $verbose_mode;
   printf STDOUT   "---------------------\n" if $verbose_mode;

   #
   # MAIN PARSING SECTION
   #
   foreach $in ( @source_file_list )  {               

       # v1.0b4 file exclusion feature
       printf STDOUT "PARSE_VHDL: The value of fileExclusionArray is \"%s\"", $fileExclusionArray{$in} if $PARSE_VHDL_tells_all;
       if ( defined($fileExclusionArray{$in})  ) {
	  # next loop please.
	  printf STDOUT "\n   File \"%s\" was excluded from parsing\n", $in if $verbose_mode;
	  next;
       }

       # set up the loop
       if ( !open (IN, $in) )  {
          printf STDOUT "Bummer, I can't open source file: $in\n";
          next; # work on the next source file.
       } else {
          printf STDOUT "\n   Surfing file \"%s\"\n", $in if $verbose_mode;
       }

       # grab the first line and prep for parsing
       $saved_line = <IN>;
       chomp $saved_line;

       # needed for advanced parsing
       $real_saved_lind = $saved_line;

       while ( eof(IN) != 1 ) {

	  printf "\nPARSE_VHDL: Working on line \"%s\" \n", $saved_line if $PARSE_VHDL_tells_all;

	  # Classify what we are looking for...
          # look for a few keys
	  $magic_block = &look_for_magic_token(*magic_block_list);
	  printf "PARSE_VHDL: Found token \"%s\" \n", $magic_block if $PARSE_VHDL_tells_all;

          # if we found something good, parse it.
	  if ( $magic_block ne "" ) {      
             &setup_VHDL_parse;

             # Parse entity
             if ( $magic_block =~ /\bentity\b/i ) {
        	&parse_entity;
        	printf "      Entity \"%s\" found\n", $entity_name if $verbose_mode;

        	# Put the entity name in the list of only entitys, and check if it is there already...
                # MUST switch to hash here.
		for ( $ord_counter2 = 0; $ord_counter2 < $entity_counter; $ord_counter2++) {
        	   #  find where the entity is in the list and save that ordinal
        	   $tempEName1 = "\U$entity_only[$ord_counter2]";
        	   $tempEName2 = "\U$entity_name";
        	   if ( $tempEName1 eq $tempEName2 ) { 
        	      printf STDOUT "DUDE: I have already seen this entity \"%s\".  This makes for bad karma.\n", $entity_name; 
        	      last;
        	   }
		}

        	$entity_only[$entity_counter] = "\U$entity_name";
        	$entityBogusNameToRealName{$entity_only[$entity_counter]} = $entity_name;
        	printf "PARSE_VHDL: entityBogusNameToRealName{%s} is %s \n", $entity_only[$entity_counter],
        	$entityBogusNameToRealName{$entity_only[$entity_counter]} if $PARSE_VHDL_tells_all;
        	$entityNameToMDAOrdinal{$entity_only[$entity_counter]} = $ordinal_counter;
        	$entity_counter++;
        	&save_parse_info("entity");
             } 

             # Parse architecture
             elsif ( $magic_block =~ /\barchitecture\b/i ) {

        	&parse_architecture;   
        	&save_parse_info("architecture");
             } 

             # Parse configuration
             elsif ( $magic_block =~ /\bconfiguration\b/i ) {
        	&parse_configuration;   
        	printf "      Configuration \"%s\" of entity \"%s\" with architecture \"%s\" found\n", 
                       $configuration_name, $configuration_ent_name, $configuration_arch_name if $verbose_mode;
        	&save_parse_info("configuration");
             } 

             # Parse package
             elsif ( $magic_block =~ /\bpackage\b/i ) {

        	&parse_package; 

        	if ( $package_name ne "" ) {  
                   $temp_package_name = "\L$package_name";
                   printf "      Package \"%s\" found\n", $temp_package_name if $PARSE_VHDL_tells_all;
        	   # this section was out, now 8/27/96 it is back in...
        	   # I think I took it out because of some false detects...
        	   # yep that was the reason, 
        	   # moved here before the package is put into the list, duh!
		   foreach $tempObject (@package_only) {
                      printf STDOUT "PARSE_VHDL: Looking at object \"%s\" in list package_only\n", $tempObject if $PARSE_VHDL_tells_all;
        	      $tempPName1 = "\U$tempObject";
        	      $tempPName2 = "\U$package_name";
        	      if ( $tempPName1 eq $tempPName2 ) { 
        		 printf STDOUT "Dude: I have already seen this package \"%s\".  This is not a good sign.\n", $package_name if $verbose_mode; 
        		 last;
        	      }
		   }
                   printf STDOUT "PARSE_VHDL: adding package \"%s\" into package_only list\n", $temp_package_name if $PARSE_VHDL_tells_all;
                   push ( @package_only, $temp_package_name);
                   $package_counter++;
                   &save_parse_info("package");
        	} else {
                   printf "      Package body \"%s\" found\n", $package_body_name if $verbose_mode;
                   # should detect duplicate package bodies here!
                   &save_parse_info("packagebody");
        	}
             } 

             # Parse the 'use' statement
             elsif ( $magic_block =~ /\buse\b/i ) {

        	do {
        	   $lib_token_temp =  &get_token( 1 );
        	   $lib_token =  "\L$lib_token_temp";
        	   $pack_token_temp =  &get_token( 2 );
        	   $pack_token =  "\L$pack_token_temp";
        	   $end_token = &get_token( 1 );

        	   # just in case the VHDL has use lib.component;
        	   if ( $end_token eq ";" ) {
        	      printf "      Component \"%s\" from library \"%s\" used.\n", $pack_token_temp, $lib_token_temp if $verbose_mode;
        	   } else {

        	      # Dirk Lucket from TI enhanced this section to nibble the tokens off one by one and test to
        	      # see if ";" is in the token.  Otherwise, problems can happen with 'use ieee.std_logic_arith."+";'
        	      while ( $end_token !~ /\;/ ) {
        		 $end_token = &get_token( 1 );
        	      }
        	      $end_token = ";";
        	      printf "      Package \"%s\" from library \"%s\" used.\n", $pack_token_temp, $lib_token_temp if $verbose_mode;

        	      push(@unitLibraryList, $lib_token );
                      push(@totalLibraryList, $lib_token );

        	      # Build a complete package name...
        	      $compete_pack_name = $lib_token . "." . $pack_token;
        	      push(@unitPackageList, $pack_token );
        	      push(@unitCompletePackageList, $compete_pack_name );

                      # Map the package to the library where it is expected to be found
                      # Make sure that it wasn't someplace else already
                      $packTokenUpper = "\U$pack_token";
                      $libTokenUpper = "\U$lib_token";
                      if ( !defined($packageName_2_LibraryName{$packTokenUpper}) ) {
                	 $packageName_2_LibraryName{$packTokenUpper} = $libTokenUpper;
                	 printf STDOUT "      Package \"%s\" is expected to be in library \"%s\" \n", $packTokenUpper, $packageName_2_LibraryName{$packTokenUpper} if $verbose_mode;
                      } elsif ( $packageName_2_LibraryName{$packTokenUpper} ne $libTokenUpper ) {
                	 printf STDOUT "   Warning: Package \"%s\" is expected to be found in more than one logical library\n", $packTokenUpper if $verbose_mode;
                      } 
        	   }
        	} until $end_token eq ";";

        	# Clean up the strings to make sure each item is only in there once
        	$temp_package_string = join(" ", @totalLibraryList);
        	@totalLibraryList = split(" ", &make_uniq_list( $temp_package_string ));

        	$temp_package_string = join(" ", @unitLibraryList);
        	@unitLibraryList = split(" ", &make_uniq_list( $temp_package_string ));


        	$temp_package_string = join(" ", @unitPackageList);
        	@unitPackageList = split(" ", &make_uniq_list( $temp_package_string ));

        	$temp_package_string = join(" ", @unitCompletePackageList);
        	@unitCompletePackageList = split(" ", &make_uniq_list( $temp_package_string ));

             } # end of the magic word if
	  } # end of the first if
       } # end of the while

       # save the package and library information for each source file here
       $sourceFile_2_packages{$in} = join( " ", @unitCompletePackageList );
       $sourceFile_2_libraries{$in} = join( " ", @unitLibraryList );

   } # end of the foreach

   # save the data file
   close MDA;
}

sub deal_with_packages {
   # if told to, create the package info
   if ( $write_packages == 1 ) {
      printf STDOUT "\nReconciling packages:\n" if $verbose_mode; 
      printf STDOUT   "---------------------\n" if $verbose_mode; 
      $MPCounter = 0;
      &merge_packages();
   }
}

sub merge_VHDL {
   # Merge all the entity/architecture/configuration/file information in a set of arrays
   printf STDOUT "\nReconciling design units:\n" if $verbose_mode; 
   printf STDOUT   "-------------------------\n" if $verbose_mode; 
   $MERGE_counter = 0;

   # Info on MERGE(d) arrays MD arrays...
   #         $MERGE_EList[]     : The working name of the entity
   #         $MERGE_ETNList[]   : The real name of the entity
   #         $MERGE_AList[]     : The architectures for the entity
   #         $MERGE_CList[]     : The configuration for the entity
   #         $MERGE_FList[]     : The list of files for the design unit
   #         $MERGE_IList[]     : The list of instances for the design unit
   #         $MERGE_CNList[]    : The list of instances:cell names for the design unit
   #         $MERGE_PList[]     : The list of parent configurations for the design unit
   #         $MERGE_KList[]     : The list of kid configurations for the design unit
   #

   $cleanHierarchy = &merge();
}

sub build_VHDL_design_hierarchy {
   printf STDOUT "\nBuilding design hierarchy:\n" if $verbose_mode;
   printf STDOUT   "--------------------------\n" if $verbose_mode;

   # Set up variables
   @masterKidList = ();
   @tempList = ();
   @topFirstList = ();
   @bottomFirstList = ();
   @tempKidList = ();
   $kidListCounter = 0;
   $topEntityMERGEOrd = 0;
   $tempConfigName = "";
   $tempOrd = 0;
   @topDesignList = ();
   @missingEntityList = ();
   @indentedUnitList = ();
   $topEntityFound = 0;
   $globalTempKid = "";
   $tempMERGEOrdinal;

   #
   # Next, find where the top_entity is in the MERGE DB
   #  A hash table would be the best way to do this...
   if ($top_entity ne "" ){
      for ($counter1 = 0; $counter1 < $MERGE_counter; $counter1++ ) {
	 if ( $top_entity eq $MERGE_EList[$counter1] ) {
	    $topEntityMERGEOrd = $counter1;
	    $topEntityFound = 1;
	    last;
	 }
      }
   }
}

sub process_VHDL_designs {      
   #
   # Now finish up by outputting script files for various tools
   #
   # If clean and listed, create the scripts
   if (($cleanHierarchy == 0) && ($top_entity ne "" )){
      if ($topEntityFound) {
	 printf STDOUT "\nThe design hierarchy for entity \"%s\" looking good, now creating scripts...\n", $top_entity if $verbose_mode;

	 # Create the design hierarchy
	 &build_design_hier;
	 &build_package_hier;

	 # Build the topDown and bottomsUp lists of entities
	 &make_ordered_ELists($top_entity, 1);
	 &make_ordered_PackageList;
	 @bottomFirstList = reverse @topFirstList;

	 $topDesign = $entityBogusNameToRealName{$top_entity};

	 # Output the desired script files...
	 &make_all_scripts( $topDesign );

	 # Produce a report file
	 &make_new_VHDL_unit_report( $topDesign );
      } elsif ( $verbose_mode == 1)  {
	 printf STDOUT "\nI can't find the entity \"%s\" that you gave me on the command line in my database, so...\n", $top_entity;
	 printf STDOUT   "Please examine the log file I spit out and make sure you find the listed entity name\n";
      }

   # Else if just clean, go and find all top entitys, and built a tree for each
   } elsif ($cleanHierarchy == 0) {

      # Create the kids/parents list
      #$BDH_tells_all = 1;
      #$BPH_tells_all = 1;
      &build_design_hier;
      &build_package_hier;

      printf STDOUT "\nDetermining all the root designs:\n" if $verbose_mode;
      printf STDOUT   "---------------------------------\n" if $verbose_mode;

      # Find all the root level designs
      &derive_hier;

      foreach $topDesign (@topDesignList) {
	 printf STDOUT   "   Entity: \"%s\"\n", $topDesign if $verbose_mode;
      }
      printf STDOUT   "\n" if $verbose_mode;

      foreach $topDesign (@topDesignList) {
	 @topFirstList = ();
	 @bottomFirstList = ();
	 @missingEntityList = ();
	 @indentedUnitList = ();

	 # Require that the design have some kids inorder to build the hier...
	 $tempMERGEOrdinal = $MERGE_entity_2_ordinal{ $topDesign };
	 $myKidsString = $MERGE_IList[ $tempMERGEOrdinal ];      

	 #  This is turned off by default, use the "-o" hidden switch to turn it on
	 if ( ($process_single_designs == 1) || ($myKidsString ne "") ) {
	    printf STDOUT "\nProcessing design hierarchy for entity \"%s\" and outputing scripts...\n", $topDesign if $verbose_mode;
	    printf STDOUT "----------------------------------------------------------------------------\n" if $verbose_mode;

	    # Build the topDown and bottomsUp lists of entities
	    &make_ordered_ELists($topDesign, 1);
	    &make_ordered_PackageList;
	    @bottomFirstList = reverse @topFirstList;

	    $top_entity = $entityBogusNameToRealName{$topDesign};

	    # Output the desired script files...
	    &make_all_scripts( $top_entity );
	    &make_new_VHDL_unit_report( $top_entity );

	 } else {
	    printf STDOUT "\nEntity \"%s\" has no children, so no scripts will be created\n", $topDesign if $verbose_mode;
	    printf STDOUT "--------------------------------------------------------------------------------\n" if $verbose_mode;
	 }

      }

   # Otherwise, give the user some feedback on the dirty designs and what to do next
   } elsif ($cleanHierarchy == 1) {
      &unclean_help;
   } elsif ($cleanHierarchy == 2) {
      # Report why the design hierarchy can't be built and 
      # tell the user how to fix it
      printf STDOUT "\n      \"HierarchySurfer, please build the design hierarchy for me now.\"\n\n";
      printf STDOUT "\n      \"No way dude!\"\n\n\n";
      printf STDOUT "\nProblem:\n";
      printf STDOUT   "--------\n";
      printf STDOUT   "There are architectures missing for the following entities!\n";
      foreach $miaa (@entitiesWithMissingArchsList) {
	 printf STDOUT "   Entity: \"%s\ \n", $miaa;
      }
   }
}

 
sub make_shfFiles_list_file {

   $mur_file = ".shf_files";
   # put this in the removal list
   push( @filesToCleanList, $mur_file );

   if ( !open(SHFOUTFILE, ">$mur_file") )  {
      print "HierachySurfer/MUR: Can't open the report file \"$mur_file\" for output!\n";
      return;
   }
   
   printf SHFOUTFILE "catch {unset surfedSHFFiles} \n" ;
   foreach $tempFile (@SHFFiles) {
      printf SHFOUTFILE "lappend surfedSHFFiles %s\n", $tempFile;
   }
   close SHFOUTFILE
}

sub check_for_right_version {
   # Check for minimum version
   if ( $] < 5 ) {
      printf STDOUT "Error:  This script requires at least verision 5 to run\n";
      printf STDOUT "        This is verision \"%s\"\n", $];
      printf STDOUT "\n\nBye!\n";
      exit;
   }
}

sub set_up_HS2 {

   # unbuffer STDOUT
   $| = 1;
   
   $numericVersion = "2.26.1";
   $version = "v" . $numericVersion;
   $targetLanguage = "VHDL";
   $surfDate = localtime(time);
   #printf STDOUT "Running under %s\n", $^O;
   if ( $^O == "MSWin32" ) {
      $surfDir = ".";
   } else {
      $surfDir = $ENV{'PWD'};
   }
   #printf STDOUT "The current working directory is %s\n", $surfDir;

   $outputDirectory = "./";
   $usage_message = 
   "HierarchySurfer 
        [-d one_or_more_directories_separated_by_the_space_character]
        [-e one_or_more_file_extensions_separated_by_the_space_character]
        [-h] -- Help, this message but you know that already!
        [-l Verilog_or_VHDL] -- The default is VHDL
        [-o the_directory_where_write_the_output_files \"./\" is default]
        [-s] -- Elaborate every single design unit, OFF by default
        [-t top_entity_or_module_name]
        [-v] -- Turn the verbose mode on, OFF by default.
        [-w] -- Write explicit configuration files, OFF by default
        [-c one_or_more_files_separated_by_the_space_character] 
             -- This is a list of file that contain library cells for
                HS2 ignore.  You can make this list from the unit_report file.       
        [-x one_or_more_files_separated_by_the_space_character] 
             -- eXclude these files from parsing, local files *must have* 
                 the \"./\" like \"./local.vhd\"
        [-z] -- Print the numeric version and die.\n";

   # HS2 defaults
   $source_dir_list[0] = ".";
   $dir_counter = 0;
   $ext_counter = 0;
   $exclusionCounter = 0;
   $top_entity = "";
   $MAIN_tells_all = 0;
   $write_packages = 1;
   $verbose_mode = 0;
   $make_cyclone = 0;
   $write_configs = 0;
   $elab_each_unit = 0;
   $removeTempFiles = 1;
   $fileExclusion = 0;
   $process_single_designs = 1;
   @source_file_list = ();
   %fileExclusionArray = ();
   $token = "NULL";
   $dont_print_leafs = 0;

   # This is the list of files that will go into a shell file that removes all files.
   @filesToCleanList = (); 

   # this is for the temp "." files
   @filesToKillList = ();           


}

sub set_up_HS {
   ######################
   #
   #  List of keywords for parsing... trust me
   #
   ######################


   @block_keywords = ( "begin" );
   @config_keywords = ( "for",  "begin", "end" );
   @ASPKeywords = ( ":", "begin", "end", "process", "block" );
   @ADPKeywords = ( "begin", "end", "component", "function", "procedure" );
   @entity_list = ("begin", "end", "port");

   @parse_package_list = ("begin", "end", "component");
   @not_quite_end_list = ("units", "record", "for",  "case", "component", "if", "generate", "loop" );

   @entity_token_list = ("begin", "end");
   @magic_symbol_list = ( ":" );
   @magic_word_list = ( "architecture", "entity", "package", 
                	"component", "library", "use", "begin", "end",
                       "configuration", "for");

   @magic_block_list = ( "use", "architecture", "entity", "package", "configuration");

   @arch_label_exclusion_list = ( "for", "while", "=", "process", "block", "assert", "<=", "with", "if" );
   @label_exclusion_list1 = ( "for", "while", "=", "process", "block", "assert", "with" );                    
   @label_exclusion_list2 = ( "<=" );         


   %MERGE_entity_2_ordinal = ();
   %sourceFile_2_packages = ();
   %sourceFile_2_libraries = ();

   $lastToken = "";

   if (@source_ext_list == () ) {
      $source_ext_list[0] = "vhd";
   }

}

sub clean_files {
###############
#
# You will never know what this sub does!!!
#
###############

   # simplified to unlink in v2.23   
   unlink @filesToKillList;
}

sub make_shell_clean_files {
###############
#
# You will never know what this sub does!!!
#
###############
   local ($execString );
   local ($cleanString );

   $cleaner_file = $outputDirectory . "Clean_HS2_files.csh";
   push( @filesToCleanList, "$cleaner_file" );

   if ( !open (CLEANER, ">$cleaner_file") )  {
      "HS2/MSCF: Can't open the file \"Clean_HS_files.csh\" for output!\n";
      return;
   }
   
   # might wish to uniq this list
   foreach $fileToKill (@filesToCleanList) {
      $execString = "rm $fileToKill > /dev/null ";
      printf CLEANER "%s\n", $execString;
   }

   # make sure the temp files are killed also...
   # foreach $fileToKill (@filesToKillList) {
   #    $execString = "rm $fileToKill > /dev/null ";
   #    printf CLEANER "%s\n", $execString;
   # }

   close CLEANER;
   
   #Make the file executable
   chmod 0744, $cleaner_file;
}

sub make_new_VHDL_unit_report {
###############
#
# This sub produces a report for the design Unit
#
###############
   local ($myName);
   local ($localName);
   local ($localTopRealName);
   local ($localReportFileName);
   local ($localUnitList);
   local ($localMERGEOrdinal);
   local (@localLibraryList);
   local (@localPackageList);
   local ($localTempString);
   local ($localTemp2String);
   local (@masterMissingInstList);
   local (@newInstanceList);
   local (@newInstanceCellNameList);
   local (@newInstanceString);
   local (@newInstanceCellNameString);
   local (@tempList);
   local (@tempItem);
   local (@tempItemsList);
   local ($tempICNString);
   local (@tempICNList);
   local ($firstItem);
      
   $myName = $_[0];
      
   $mur_root = $myName . ".unit_report";
   $mur_file = $outputDirectory . $mur_root;
   # put this in the removal list
   push( @filesToCleanList, $mur_file );

   if ( !open(REPORT, ">$mur_file") )  {
      "HierachySurfer/MUR: Can't open the report file \"$mur_file\" for output!\n";
      return;
   }

   # Spit up some header information...
   printf REPORT "Design unit report file for root design \"%s\", from HierarchySurfer %s!\n\n", $myName, $version;

   @localUnitList = reverse(@indentedUnitList);
   # First print the Unit listing
   printf REPORT "The top down listing of entities is:\n";
   printf REPORT "------------------------------------\n";
   foreach $localName (@localUnitList) {
      printf REPORT "   %s\n", $localName;
   }
   
   #$MERGE_MIAList
      
   # For each unit, print all the MERGE info...
   printf REPORT "\nDetailed information for all entities:\n";
   printf REPORT "--------------------------------------\n";
   @localUnitList = reverse(@topFirstList);
   foreach $localName (@localUnitList) {
      $localTopRealName = $entityBogusNameToRealName{$localName};
      $localMERGEOrdinal = $MERGE_entity_2_ordinal{ $localName };
      if ( $MERGE_CList[ $localMERGEOrdinal] == -1 ) {
         $localTemp2String = "There were no explicit configurations found";
      } else {
         $localTemp2String = "$MERGE_CList[ $localMERGEOrdinal]";
      }

      # Precondition the IList and CNList variables
      @newInstanceList = ();
      @newInstanceCellNameList = ();         
      
      # fix to get the 'real' entity names sub-designs line    
      @tempList = split(" " ,$MERGE_IList[ $localMERGEOrdinal]);
      foreach $tempItem (@tempList) {

         # make sure the merge ordinal is in range
         if ( defined($MERGE_entity_2_ordinal{$tempItem}) ) {
            push( @newInstanceList, $MERGE_ETNList[ $MERGE_entity_2_ordinal{ $tempItem } ]);
         } else {
            
            # added in v2.24 to case correct missing entities
            if ( defined($instanceName2instanceTrueName{$tempItem}) ) {
               $tempItem = $instanceName2instanceTrueName{$tempItem};
            }
            push( @newInstanceList,  $tempItem );
         }
      }
      
      # fix to get the 'real' entity names in the sub-design:Cell name line    
      @tempList = split(" " ,$MERGE_CNList[ $localMERGEOrdinal]);
      foreach $tempItem (@tempList) {
         # split the item, then change the case correct the first element and rejoin.
         @tempICNList = split(':', $tempItem);
         
         # make sure the merge ordinal is in range
         if ( defined($MERGE_entity_2_ordinal{$tempICNList[0]}) ) {
            # I says intermediate variables be damned!
            $tempICNString =   $tempICNList[1] . " (" . $MERGE_ETNList[ $MERGE_entity_2_ordinal{ $tempICNList[0] } ] . ")";
         } else {
            # added in v2.24 to case correct missing entities
            if ( defined($instanceName2instanceTrueName{$tempICNList[0]}) ) {
               $tempItem = $instanceName2instanceTrueName{$tempICNList[0]};
            }
         
            $tempICNString =   $tempICNList[1] . " (" . $tempItem . ")";
         }
         #printf STDOUT "MNVUR: The merge ordinal for \"%s\" is \"%s\"\n", $tempICNList[0], $MERGE_entity_2_ordinal{ $tempICNList[0] };
         #printf STDOUT "MNVUR: The orignial string is \"%s\"\n", $tempItem;
         #printf STDOUT "MNVUR: The case corrected string is \"%s\"\n", $tempICNString;
         push( @newInstanceCellNameList, $tempICNString);
      }

      printf REPORT "\n   Entity \"%s\":\n", $localTopRealName ;
      printf REPORT   "   ===============================================\n";
      printf REPORT "      Entity name            : %s\n", $MERGE_ETNList[ $localMERGEOrdinal];
      printf REPORT "      Architecture name      : %s\n", $MERGE_AList[ $localMERGEOrdinal];
      printf REPORT "      Configuration name     : %s\n", $localTemp2String;

      # put out the files in the new format
      printf REPORT "      Files                  : ";
      if ($MERGE_FList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_FList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      
      # put out the sub-designs in the new format
      printf REPORT "      Sub-designs            : ";
      if ($MERGE_IList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = @newInstanceList;
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      

      # put out the sub-designs/Cell Names in the new format
      printf REPORT "      Cell name (Sub-design) : ";
      if ($MERGE_CNList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = @newInstanceCellNameList;
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      

      # put out the parent in the new format
      printf REPORT "      Parent configurations  : ";
      if ($MERGE_PList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_PList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      
      # put out the child configurations in the new format
      printf REPORT "      Child configurations   : ";
      if ($MERGE_KList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_KList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      
      # put out the libraries in the new format
      printf REPORT "      Libraries used         : ";
      if ($MERGE_LibraryList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_LibraryList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
            
      # put out the packages in the new format
      printf REPORT "      Packages used          : ";
      if ($MERGE_PackageList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_PackageList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
            
      # put out the MIA in the new format
      printf REPORT "      Unresolved instances   : ";
      if ($MERGE_MIAList[ $localMERGEOrdinal] ne "" ) {
         @tempItemsList = split(' ', $MERGE_MIAList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $tempItem (@tempItemsList) {
            if ($firstItem == 0) {
               printf REPORT "                               %s\n", $tempItem;
            } else {
               printf REPORT "%s\n", $tempItem;
               $firstItem = 0;
            }
         }
      } else {
         printf REPORT "\n";
      }
      
      push( @masterMissingInstList, $MERGE_MIAList[$localMERGEOrdinal] );
      push( @localLibraryList, $MERGE_LibraryList[ $localMERGEOrdinal] );
   }
      
   # For each unit, print all the MERGE PACKAGE info...
   printf REPORT "\nDetailed information for all parsed packages:\n";
   printf REPORT   "---------------------------------------------\n";
   @localPackageList = reverse(@orderedPackageList);
   foreach $localName (@localPackageList) {
      $localMERGEOrdinal = $MPPackageName_2_MPCounter{ $localName };
      printf REPORT "\n   Package \"%s\":\n", $MP_PList[ $localMERGEOrdinal] ;
      printf REPORT   "   ===============================================\n";
      printf REPORT "      Header File            : \"%s\"\n", $MP_FList[ $localMERGEOrdinal];
      printf REPORT "      Body File              : \"%s\"\n", $MP_PBFList[ $localMERGEOrdinal];
#      printf REPORT "      Parent packages        : \"%s\"\n", $MERGE_PList[ $localMERGEOrdinal];
#      printf REPORT "      Libraries used         : \"%s\"\n", $MERGE_LibraryList[ $localMERGEOrdinal];
      printf REPORT "      Packages used          : \"%s\"\n", $MP_KList[ $localMERGEOrdinal];
   }
   
   # Report on logical libraries
   printf REPORT "\nThe list of logical libraries used in the design is:\n";
   printf REPORT   "----------------------------------------------------\n";
   $localTempString = &make_uniq_list(join(" ", @localLibraryList));
   @localLibraryList = split(" ", $localTempString);
   foreach $localName (@localLibraryList) {
      printf REPORT "   \"%s\"\n", $localName;
   }
   
# Report on packages
   if ( (@orderedPackageList != ()) || (@notParsedPackageList != ()) ) {
      printf REPORT "\nThe packages needed in the design are:\n";
      printf REPORT   "--------------------------------------\n";
   }
   
   if ( @orderedPackageList != () ) {
      printf REPORT "   Found among parsed files:\n";
      printf REPORT "   =========================\n";
      foreach $localName (@orderedPackageList) {
         printf REPORT "      \"%s\"\n", $localName;
      }
   }

   if ( @notParsedPackageList != () ) {
      printf REPORT "\n   Not found among parsed files:\n";
      printf REPORT   "   =============================\n";
      foreach $localName (@notParsedPackageList) {
         printf REPORT "      \"%s\"\n", $localName;
      }
   }

# List any combined files
   if ( @combinedFileList != () ) {
      printf REPORT "\nThe list of combined files for HDL Advisor is:\n";
      printf REPORT   "----------------------------------------------\n";
      foreach $localName (@combinedFileList) {
	 printf REPORT "   \"%s\"\n", $localName;
      }
   } 
   
   # Finish with the list of possibly missing components...
   $missingInstancesString = &make_uniq_list( join(" ", @masterMissingInstList ) );
   @missingInstancesList = split(" ", $missingInstancesString);
# Used to report @missingEntityList
   if ( @missingInstancesList != () ) {
      printf REPORT "\nThe list of missing instances is:\n";
      printf REPORT   "---------------------------------\n";
      foreach $localName (@missingInstancesList) {
         printf REPORT "   \"%s\"\n", $localName;
      }
      printf REPORT "\n   Well, I looked high and low, but I could find these instances in\n";
      printf REPORT "   the entities or components declared in arches and used, parsed packages.\n";
      printf REPORT "   This may not be a big deal as along as the above list can\n";
      printf REPORT "   be found in a used package that I didn't parse.  Start looking!\n";
   } else {
      printf REPORT "\nMost cool! All instances were resolved for this design hierarchy!! \n" if $verbose_mode;
   }
}

sub make_ordered_PackageList{
###############
#
# This sub produces the ordered list of packages for later usage
# based on the topFirstList from make_ordered_ELists
#
# $MPPackageName_2_MPCounter{$tempPackageName}
#
# Returns @orderedPackageList and @notParsedPackageList
# 
###############
   local( $myMERGEOrdinal );
   local( $localEntity );
   local( $notInList );
   local( $matchFound );
   local( $item1 );
   local( $item2 );
   local( $item3 );
   local( @rawPackageList );
   local( @masterPackageList );
   local( @nextPackageList );
   local( @rawUsedPackageList );
   local( @usedPackageList );
   local( %entityPackages_2_Nothing );
   
   #clear the ordered list
   @orderedPackageList  = ();
   @notParsedPackageList  = ();
   
   # first gather all the packages in the design hierarchy
   foreach $localEntity (@topFirstList) {
      $myMERGEOrdinal = $MERGE_entity_2_ordinal{ $localEntity };
      push( @rawPackageList, $MERGE_PackageList[$myMERGEOrdinal]);
      printf STDOUT "MOP: The packages used in design \"%s\" are \"%s\"\n", $localEntity, $MERGE_PackageList[$myMERGEOrdinal] if $MOP_tells_all;
   }
   
   # make the list uniq
   $tempString = &make_uniq_list( join(" ", @rawPackageList));
   @rawPackageList = split(" ", $tempString);
   printf STDOUT "MOP: The complete list of packages is \"%s\"\n", join(" ", @rawPackageList) if $MOP_tells_all;

   # use each packages as an array key
   foreach $item1 (@rawPackageList) {
      $entityPackages_2_Nothing{$item1} = "true"
   }

   # order the list
   @masterPackageList = @rawPackageList;
   
   while ( @masterPackageList != () ) {
      printf STDOUT "   MOP: The masterPackageList package list is \"%s\"\n", join(" ", @masterPackageList) if $MOP_tells_all;
      printf STDOUT "   MOP: The orderedPackageList package list is \"%s\"\n", join(" ", @orderedPackageList) if $MOP_tells_all;
      @nextPackageList = ();
      foreach $item1 (@masterPackageList) {
         $item1Ord = $MPPackageName_2_MPCounter{$item1};
         if (!defined( $MPPackageName_2_MPCounter{$item1} ) ) {
            printf STDOUT "      MOP: Used package \"%s\" was not parsed, so it is ignored\n", $item1 if $MOP_tells_all;
            push( @notParsedPackageList, $item1 );
         }
         elsif ( $MP_KList[$item1Ord] eq ""  ) {
            printf STDOUT "      MOP: Package \"%s\" is clean, put into ordered list\n", $item1 if $MOP_tells_all;
            push( @orderedPackageList, $item1 );
         } else {
            @rawUsedPackageList = split(" ", $MP_KList[$item1Ord]);
            @usedPackageList = ();
            printf STDOUT "      MOP: Package \"%s\" depends on packages \"%s\"\n", $item1, $MP_KList[$item1Ord] if $MOP_tells_all;
            
            # Remove packages that aren't package_only list here
            foreach $item2 (@rawUsedPackageList) {
               if ( defined($MPPackageName_2_MPCounter{$item2}) ) {
                  push(@usedPackageList, $item2 );
               }
            }
            printf STDOUT "      MOP: Package \"%s\" depends on parsed packages \"%s\"\n", $item1, join(" ", @usedPackageList) if $MOP_tells_all;
           
            printf STDOUT "      MOP: Now scanning the ordered package list for package \"%s\" dependancies \n", $item1 if $MOP_tells_all;
            #
            # notInList was not initialized properly and causing infinite loop, added init statement
            # fixed by Dirk R. Luckett from TI               
            $notInList = 0;   
            foreach $item2 (@usedPackageList) {
               $matchFound = 0;
               foreach $item3 (@orderedPackageList) {
                  if ( $item3 eq $item2 ) {
                     $matchFound = 1;
                     printf STDOUT "         MOP: Package \"%s\" is already in the ordered list\n", $item2 if $MOP_tells_all;
                     last;
                  }
               }
               if ( $matchFound != 1 ) {

                  # If the package not found in the ordered list
                  # but it is in the MP list and not in the entity list
                  # This is a hidden dependancy, so push that package into
                  # the ordered list
                  if( (defined( $MPPackageName_2_MPCounter{$item2})) && (!defined($entityPackages_2_Nothing{$item2})) ) {
                     $notInList = 0;
                     push(@orderedPackageList, $item2 );
                  } else {
                     $notInList = 1;
                     last;
                  }
               } else {
                  $notInList = 0;
               }
            }
            if ( $notInList == 1 ) {
               push( @nextPackageList, $item1 );
               printf STDOUT "      MOP: Package \"%s\" is not clean, put into next list\n", $item1 if $MOP_tells_all;
            } else {
               push( @orderedPackageList, $item1 );
               printf STDOUT "      MOP: Package \"%s\" is now clean, put into ordered list\n", $item1 if $MOP_tells_all;
            }
         }
      }
      printf STDOUT "   MOP: The nextPackageList package list is %s\n", join(" ", @nextPackageList) if $MOP_tells_all;
      @masterPackageList = @nextPackageList;
   }
   
   printf STDOUT "MOP: The ordered package list is %s\n", join(" ", @orderedPackageList) if $MOP_tells_all;

}

sub make_ordered_ELists {
###############
#
# This sub produces the ordered entity lists for later usage
# Note that this is a recursive process... 
#
# This also fills the missingEntityList and indentedUnitList variables...
#
# v2.23: Case corrected the Entity names in the SHF strings.
#
###############
   local ($myName);
   local ($myRealName);
   local ($myLevel);
   local ($myLevelName);
   local ($myBlankString);
   local ($myKidsString);
   local ($myTempKid);
   local ($myTempCounter);
   local (@myKidsList);
   local ($myMERGEOrdinal);
   local (@itemNamesList);
   local ($myTempMERGEOrdinal);
   local ($myTempRealName);
   
   printf STDOUT "\nMOEL: Called with value \"%s\"\n", $_[0] if $MOEL_tells_all;
   $myName = $_[0];
   $myLevel = $_[1];
      
   if ( $myLevel == 1 ) {
      $SHF2_string = " ";
   }
   
   $myBlankString = " ";
   # Build the indented string for later usage...
   for ( $myTempCounter = 0; $myTempCounter < $myLevel; $myTempCounter++) {
      $myBlankString = $myBlankString . "   ";
   }

   # Need to check if the entity was found
   if ( defined($MERGE_entity_2_ordinal{ $myName })  ) {
     
      $myMERGEOrdinal = $MERGE_entity_2_ordinal{ $myName };
      $myRealName = $MERGE_ETNList[ $myMERGEOrdinal ];

      # First, put me in the list
      push (@topFirstList, $myName);
      $SHF2_string = $SHF2_string . " { " . $myName;

      # Now, if I have any kids, call this routine for each of them...
      $myKidsString = $MERGE_IList[ $myMERGEOrdinal ];

      printf STDOUT "%sMOEL: The value of myName is \"%s\"\n", $myBlankString, $myName if $MOEL_tells_all;
      printf STDOUT "%sMOEL: The value of myMERGEOrdinal is \"%s\"\n", $myBlankString, $myMERGEOrdinal if $MOEL_tells_all;
      printf STDOUT "%sMOEL: The value of myKidsString is \"%s\"\n", $myBlankString, $myKidsString if $MOEL_tells_all;

      if ( $myKidsString ne "" ) {
	 @myKidsList = split(' ', $myKidsString);
         $SHF2_string = $SHF2_string . " { " ;
	 foreach $myTempKid ( @myKidsList ) {
            printf STDOUT "%sMOEL: The value of myName is \"%s\", my kid is named \"%s\"\n", $myBlankString, $myName, $myTempKid if $MOEL_tells_all;
            # The key must be case correct
            $globalTempKid = "\U$myTempKid";
            &make_ordered_ELists($globalTempKid, ($myLevel+1));
	 }
         $SHF2_string = $SHF2_string . " } ";
      } else {
         $SHF2_string = $SHF2_string . " {} ";
      }
      
      # now add the extra info to the SHF string
      $extraInfoString = "";
      $localTopRealName = $entityBogusNameToRealName{$myName};
      $localMERGEOrdinal = $MERGE_entity_2_ordinal{ $myName };
      if ( $MERGE_CList[ $localMERGEOrdinal] == -1 ) {
	 $localTemp2String = "None found";
      } else {
	 $localTemp2String = "$MERGE_CList[ $localMERGEOrdinal]";
      }

      $extraInfoString = $extraInfoString . "Entity name            : " . $MERGE_ETNList[ $localMERGEOrdinal]     . "\n";
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Architecture name      : " . $MERGE_AList[ $localMERGEOrdinal]       . "\n";
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "Configuration name     : "   . $localTemp2String                       . " \n";
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "File name(s)           : ";
      if ($MERGE_FList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_FList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";

      $extraInfoString = $extraInfoString . "Libraries used         : ";
      if ($MERGE_LibraryList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_LibraryList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Packages used          : ";
      if ($MERGE_PackageList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_PackageList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Sub-designs            : ";
      if ($MERGE_IList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_IList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
             
            # fix to get the 'real' entity names in the SHF
            if ( defined($MERGE_entity_2_ordinal{ $item }) ) {
               $myTempMERGEOrdinal = $MERGE_entity_2_ordinal{ $item };
               $myTempRealName = $MERGE_ETNList[ $myTempMERGEOrdinal ];
            } else {
               # added in v2.24 to case correct missing entities
               if ( defined($instanceName2instanceTrueName{$item}) ) {
                  $item = $instanceName2instanceTrueName{$item};
               }
               $myTempRealName = $item
            }

            $extraInfoString = $extraInfoString . $myTempRealName . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";

      $extraInfoString = $extraInfoString . "Sub-design cells       : Entity Name Cell name \n";
      if ($MERGE_CNList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_CNList[ $localMERGEOrdinal]);

         # need to fix this to put in the real entity names here also (like above)
         foreach $item (@cellNamesList) {
            $extraInfoString = $extraInfoString . "                         ";
            @itemNamesList = split(':', $item);
            
            # fix to get the 'real' entity names in the SHF
            if ( defined($MERGE_entity_2_ordinal{ $itemNamesList[0] }) ) {
               $myTempMERGEOrdinal = $MERGE_entity_2_ordinal{ $itemNamesList[0] };
               $myTempRealName = $MERGE_ETNList[ $myTempMERGEOrdinal ];
            } else {
               # added in v2.24 to case correct missing entities
               if ( defined($instanceName2instanceTrueName{$itemNamesList[0]}) ) {
                  $item = $instanceName2instanceTrueName{$itemNamesList[0]};
               }
               $myTempRealName = $item
            }

            #$extraInfoString = $extraInfoString . $itemNamesList[1] . " (" . $myTempRealName . ")\n";
            $extraInfoString = $extraInfoString . $myTempRealName . ":" . $itemNamesList[1] . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";

      $extraInfoString = $extraInfoString . "Parent configurations  : ";
      if ($MERGE_PList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_PList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";

      $extraInfoString = $extraInfoString . "Child configurations   : ";
      if ($MERGE_KList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_KList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";

      $extraInfoString = $extraInfoString . "Unresolved instances   : ";
      if ($MERGE_MIAList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(' ', $MERGE_MIAList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }

      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Input ports            : ";
      if ( $entity_2_input{$myName} ne "") {
	 @portList = split(" ", $entity_2_input{$myName} );
	 $firstItem = 1;
	 foreach $item (@portList) {
	    if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
	    } else {
               $firstItem = 0;
	    }
	    $extraInfoString = $extraInfoString . $item . "\n";
	 }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }

      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Output ports           : ";
      if ( $entity_2_output{$myName} ne "") {
	 @portList = split(" ", $entity_2_output{$myName} );
	 $firstItem = 1;
	 foreach $item (@portList) {
	    if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
	    } else {
               $firstItem = 0;
	    }
	    $extraInfoString = $extraInfoString . $item . "\n";
	 }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }

      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Buffer ports           : ";
      if ( $entity_2_buffer{$myName} ne "") {
	 @portList = split(" ", $entity_2_buffer{$myName} );
	 $firstItem = 1;
	 foreach $item (@portList) {
	    if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
	    } else {
               $firstItem = 0;
	    }
	    $extraInfoString = $extraInfoString . $item . "\n";
	 }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }

      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "Inout ports            : ";
      if ( $entity_2_inout{$myName} ne "") {
	 @portList = split(" ", $entity_2_inout{$myName} );
	 $firstItem = 1;
	 foreach $item (@portList) {
	    if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                         ";
	    } else {
               $firstItem = 0;
	    }
	    $extraInfoString = $extraInfoString . $item . "\n";
	 }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
   } else {
      
      # case correct the entity name
      if ( defined($instanceName2instanceTrueName{$myName}) ) {
         $myName = $instanceName2instanceTrueName{$myName};
      }
      
      push( @missingEntityList, $myName);
      $myRealName = $myName . " (Entity not among given source files)";
      $SHF2_string = $SHF2_string . " { " . $myName . " {} ";

      # now add the extra info to the SHF string
      $extraInfoString = "";

      $extraInfoString = $extraInfoString . "Entity name            : " . $myName  . "\n\n";
      $extraInfoString = $extraInfoString . "Architecture name      : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Configuration name     : Unknown\n\n";
      $extraInfoString = $extraInfoString . "File name(s)           : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Libraries used         : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Packages used          : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Sub-designs            : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Sub-design cells       : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Parent configurations  : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Child configurations   : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Unresolved instances   : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Unresolved instances   : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Input ports            : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Output ports           : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Buffer ports           : Unknown\n\n";
      $extraInfoString = $extraInfoString . "Inout ports            : Unknown\n\n";
   }
   

   $SHF2_string = $SHF2_string . "{" . $extraInfoString . " }}";
   
   $myLevelName = $myBlankString . $myRealName;
   push (@indentedUnitList, $myLevelName);

}

sub make_all_scripts {
###############
#
# All script generating subroutines MUST detect un-used parents!!!!
#
#  Someday this may be true for unresolved kids too...
#
###############
   
   local  ($baseName);
   local  ($tempName);
   local  ($tempOrd);
   local  ($dirtyHier);
   
   $baseName = $_[0];
   
   $dirtyHier = 0;
   # Vomit out the list of entity in this design...
   printf STDOUT "   This design contains the following entities \n" if $verbose_mode;
   foreach $tempName ( @bottomFirstList ) {
      printf STDOUT "      Entity: \"%s\" \n", $entityBogusNameToRealName{$tempName} if $verbose_mode;
      
      # Count the number of entities missing instances
      $tempOrd = $MERGE_entity_2_ordinal{ $tempName };
      if ( $MERGE_MIAList[ $tempOrd ] ne "" ) {
         $dirtyHier++;
      }
   }
      
   # Spit out a warning message about missing instances here
   $tempName = $baseName . ".unit_report";
   if ( $dirtyHier != 0 ) {
      printf STDOUT "\n   Like, WARNING, dude: This design contains %d entities with instances that I \n", $dirtyHier;
      printf STDOUT "                        could not resolve.  Check out the unit report file\n";
      printf STDOUT "                        \"%s\" for more details\n\n",$tempName;
   }

   # Make a file for DesignSufer to display
   &make_VHDL_SHF2_file( $baseName );
      
   # Make a DesignCompiler analyze/elaborate script
   $dcFileName = $baseName . ".scr";
   &make_DC_script( $dcFileName );

   # Make a simple DC makefile...
   &make_syn_makefile( $baseName );

   # Make a VSS vhdlan script
   $vssFileName = $baseName . "_vss.csh";
   &make_VSS_script( $vssFileName );

   # Make a simple simulation makefile...
   &make_sim_makefile( $baseName );

   # Make a HDL Advisor scripts (a setup file and a ha_shell file)
   $hdlaSetupFileName = $baseName . "_ha.setup";
   $hdlaShellFileName = $baseName . "_ha.shell";
   &make_HDLA_script( $hdlaSetupFileName, $hdlaShellFileName );

   # Make a Cyclone scripts, if allowed
   
   if ($make_cyclone == 1) {
      $cyanFileName  = $baseName . "_cyan.csh";
      $cylabFileName = $baseName . "_cylab.csh";
      &make_Cy_script( $cyanFileName, $cylabFileName);
   }
}

sub make_syn_makefile {
###########
#
# Produce a stupid DC makefile
#
###########
   local ($localTopDesign) = $_[0];
   $dcFileName = "Makefile_" . $localTopDesign . ".dc";

}

sub make_sim_makefile {
###########
#
# Produce a stupid simulation analyze Makefile
#
# packageName_2_LibraryName
#        $MERGE_ordinal_2_ent_MDAordinal{ $MERGE_counter }
#        $MERGE_ordinal_2_arch_MDAordinal{ $MERGE_counter }
#        $MERGE_ordinal_2_config_MDAordinal{ $MERGE_counter }
#
###########
   local ($tempObject1);
   local ($tempObject2);
   local ($tempEntFile);
   local ($tempConfigFile);
   local ($tempArchFile);
   local ($tempEntity);
   local ($tempConfig);
   local ($tempArch);
   local ($tempKids);
   local ($tempKidList);
   local ($tempString);
   local ($tempOrdinal);
   local ($entityNotInList);
   local ($source_dir_counter);
   local (@tempList);
   local ($tempPackage);
   local (@processedEntityList);
   local (@processedPackageList);
   local (%processedFileArray);
   local (@designUnitTargets);
   local ($localTopDesign) = $_[0];
   
   $simMakefileName_root = "Sim_makefile_" . $localTopDesign;
   $simMakefileName = $outputDirectory . $simMakefileName_root;
   # put this in the removal list
   push( @filesToCleanList, $simMakefileName );

   if ( !open(SMFN, ">$simMakefileName") )  {
      "HierachySurfer/MSM: Can't open the sim make file \"$simMakefileName\" for output!\n";
      return;
   }

   printf SMFN "\# Makefile for simulation analyze \n";  
   printf SMFN "\# Spewed from HierarchySurfer(%s)!\n\n", $version; 
   printf SMFN "\# Some things are going to need to be edited for this to work\n"; 
   
   # Print the macros simple stuff first
   printf SMFN "\n\# \n";
   printf SMFN "\# Define the basic make Macros (should not have to edit) \n";
   printf SMFN "ANALYZE_COMMAND = vhdlan\n";
   printf SMFN "ANALYZE_OPTIONS = -nc\n";  
   printf SMFN "SIM_EXTENTION = sim \n";
   
  # This is turned off until I have time to fix the /home/erik/source/file.vhd issues
  # printf SMFN "\n\# \n";
  # printf SMFN "\# You don't have to edit this, but you can if you want  \n";
  # printf SMFN "\# This is prefix to the path to the source files \n";
  # printf SMFN "\# HierarchySurfer uses relative paths by default, so if you move the make, change this. \n";
  # printf SMFN "SOURCE_DIR_PATH = . \n";   
   
   printf SMFN "\n\# \n";
   printf SMFN "\# YOU MUST EDIT THIS!!  \n";
   printf SMFN "\# This is the actual directory location of the work logical library \n";
   printf SMFN "\# You are going to want make this the same as your .synopsys_vss.setup file \n";
   printf SMFN "WORK_DIR_PATH =  \n";


#
#  This is turned off until a more general solution is devised to hand work and non-work logical libs.
#
#  HS first needs to determine what library a design unit is to be found...  Then
#  This macros make sense to use, now they are just confusing..
#
   # Build the list of Design unit logical library and directory mapping macros
#   $source_dir_counter = 1;
#   printf SMFN "\n\#\n";
#   printf SMFN "\# Here are the macros for the source directories\n";
#   printf SMFN "\# These give info about any non \"WORK\" logical libraries for the source files\n";
#   printf SMFN "\# Currently, HS puts all source files into \"WORK\" \n";
#   printf SMFN "\# If you want to (or have to) change this, set these to something different\n";
#   printf SMFN "\#   The \"_WORK_DIR_PATH\" is the actual location of the logical library\n";
#   printf SMFN "\#   The \"_WORK_LOGICAL_LIB\" is the name of the logical library\n";
#   printf SMFN "\#   The prefix (SOURCEX) is just a counter for the surfed directories\n";

#   foreach $tempLibrary ( @source_dir_list ) {
#      # each library can have a different work dir path and logical library
#      $libraryWorkDirPath = "SOURCE" . $source_dir_counter . "_WORK_DIR_PATH";
#      $libraryWorkLogicalLibrary = "SOURCE" . $source_dir_counter . "_WORK_LOGICAL_LIB";
#      printf SMFN "%s = \n", $libraryWorkDirPath;
#      printf SMFN "%s = \n", $libraryWorkLogicalLibrary ;
#      $source_dir_counter++;
#   }

   # Build the list of package logical library and directory mapping macros
   printf SMFN "\n\#\n";
   printf SMFN "\# YOU MUST EDIT THIS IF YOU DEFINE YOUR OWN PACKAGE LOGICAL LIBRARIES!!  \n";
   printf SMFN "\# Here are the macros for the package directories\n";
   printf SMFN "\# These give info about any non \"WORK\" logical libraries for the package files\n";
   printf SMFN "\# Currently, HS trys to put all packages into their proper logical library\n";
   printf SMFN "\# If you want to (or have to) change this, set these to something different\n";
   printf SMFN "\#   The \"_WORK_DIR_PATH\" is the actual location of the logical library\n";
   printf SMFN "\#   The \"_WORK_LOGICAL_LIB\" is the name of the logical library\n";
   printf SMFN "\#   The prefix is just the name for the library\n";
   foreach $tempLibrary ( @totalLibraryList ) {
      $tempLibraryUpper = "\U$tempLibrary";
      # each library can have a different work dir path and logical library
      
      if ( $tempLibraryUpper ne "WORK") {
	 $libraryWorkDirPath = $tempLibraryUpper . "_WORK_DIR_PATH";
	 $libraryWorkLogicalLibrary = $tempLibraryUpper . "_WORK_LOGICAL_LIB";
	 printf SMFN "%s = .\n", $libraryWorkDirPath;
	 printf SMFN "%s = %s\n", $libraryWorkLogicalLibrary, $tempLibraryUpper ;
      }
   }

   # Write the defaults
   printf SMFN  "\n\# \n";
   printf SMFN  "\# Master Target: all the design units and packages\n";
   printf SMFN  "\# \n";
   printf SMFN  "all : \\\n";      
   printf SMFN  "  all_designUnits ";      
   
   # if turned on, do the make info for the packages
   if ($write_packages == 1 ) {
      printf SMFN  "\\\n";      
      printf SMFN  "  all_packages \n\n";      
      printf SMFN  "\# Do the package targets \n\n";
      foreach $tempPackage (@orderedPackageList) {
         $tempPackageUpper = "\U$tempPackage";
         
         printf STDOUT "MSimMF: Process package \"%s\" into library \"%s\" \n", $tempPackage, $packageName_2_LibraryName{$tempPackageUpper} if $MSimMF_tells_all;
         $tempObject1 = $MPPackageName_2_MPCounter{$tempPackage};
         $tempString = $MP_FList[$tempObject1];
         
         # Build the MACRO for the logical library
         if ( $packageName_2_LibraryName{$tempPackageUpper} ne "WORK") {
            $packageWorkLogicalLibrary = $packageName_2_LibraryName{$tempPackageUpper} . "_WORK_LOGICAL_LIB";
            $packageWorkDirPath = $packageName_2_LibraryName{$tempPackageUpper} . "_WORK_DIR_PATH";
         } else {
            $packageWorkLogicalLibrary = "WORK_LOGICAL_LIB";
            $packageWorkDirPath = "WORK_DIR_PATH";
         }

         printf STDOUT "MSimMF: Package is built from these files \"%s\" \n", $tempString if $MSimMF_tells_all;
         # first do the package header
         $tempObject2 = $MP_PDFList[$tempObject1];
         if ( !defined ( $processedFileArray{$tempObject2}) ) {
            # create the target 
            printf STDOUT "   MSimMF: Processing file \"%s\" \n", $tempObject2 if $MSimMF_tells_all;
            printf SMFN  "\# \n";
            printf SMFN  "\# Target: \"%s\" package\n", $tempPackageUpper;
            printf SMFN  "\${%s}/%s.\${SIM_EXTENTION} : \\\n", $packageWorkDirPath, $tempPackageUpper;
            # create the source dependancies
            #printf SMFN  "  \${SOURCE_DIR_PATH}/%s", $tempObject2;
            printf SMFN  "  %s", $tempObject2;

            # create any the child dependancies, will need control logic here...
            printf STDOUT "   MSimMF: File dependencies \"%s\" \n", $MP_KList[$tempObject1] if $MSimMF_tells_all;
            @tempKidList = split(" ", $MP_KList[$tempObject1]);
            foreach $tempKid ( @tempKidList ) {
               if ( defined($MPPackageName_2_MPCounter{$tempKid}) ) {
        	  printf SMFN  " \\\n";
        	  $upperCaseTempKid = "\U$tempKid";
        	  if ($packageName_2_LibraryName{$upperCaseTempKid} eq "WORK" ) {
        	     $tempPackageWorkLogicalLibrary = "WORK_DIR_PATH"; 
        	  } else {
        	     $tempPackageWorkLogicalLibrary = $packageName_2_LibraryName{$upperCaseTempKid} . "_WORK_DIR_PATH"; 
        	  }
        	  printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION}", $tempPackageWorkLogicalLibrary, $upperCaseTempKid;
               }
            }
            printf SMFN  "\n";

            # create the commands
            if ( $packageWorkLogicalLibrary eq "WORK_LOGICAL_LIB" ) {
               printf SMFN  "\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempObject2;
            } else {
               printf SMFN  "\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $packageWorkLogicalLibrary, $tempObject2;
            }

            # for debug, I think...
            $processedFileArray{$tempObject2} = "make_sim_makefile problem!!";
            $tempPackageTarget = "\${" . $packageWorkDirPath . "}/$tempPackageUpper.\${SIM_EXTENTION}";
            push(@processedPackageList, $tempPackageTarget);
         }

         $tempObject2 = $MP_PBFList[$tempObject1];
         if ( (!defined ( $processedFileArray{$tempObject2})) && ($MP_PBFList[$tempObject1] ne $MP_PDFList[$tempObject1])) {
            # create the target 
            printf STDOUT "   MSimMF: Processing file \"%s\" \n", $tempObject2 if $MSimMF_tells_all;
            printf SMFN  "\# \n";
            printf SMFN  "\# Target: \"%s__\" package body\n", $tempPackageUpper;
            printf SMFN  "\${%s}/%s__.\${SIM_EXTENTION} : \\\n", $packageWorkDirPath, $tempPackageUpper;
            # create the source dependancies
     #       printf SMFN  "  \${SOURCE_DIR_PATH}/%s \\\n", $tempObject2;
            printf SMFN  "  %s \\\n", $tempObject2;
            
            # create the package header dependancies
            printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION}", $packageWorkDirPath, $tempPackageUpper;

            # create any the child dependancies, will need control logic here...
            printf STDOUT "   MSimMF: File dependencies \"%s\" \n", $MP_KList[$tempObject1] if $MSimMF_tells_all;
            @tempKidList = split(" ", $MP_KList[$tempObject1]);
            foreach $tempKid ( @tempKidList ) {
               if ( defined($MPPackageName_2_MPCounter{$tempKid}) ) {
        	  printf SMFN  " \\\n";
        	  $upperCaseTempKid = "\U$tempKid";
        	  if ($packageName_2_LibraryName{$upperCaseTempKid} eq "WORK" ) {
        	     $tempPackageWorkLogicalLibrary = "WORK_DIR_PATH"; 
        	  } else {
        	     $tempPackageWorkLogicalLibrary = $packageName_2_LibraryName{$upperCaseTempKid} . "_WORK_DIR_PATH"; 
        	  }
        	  printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION}", $tempPackageWorkLogicalLibrary, $upperCaseTempKid;
               }
            }
            printf SMFN  "\n";

            # create the commands
            if ( $packageWorkLogicalLibrary eq "WORK_LOGICAL_LIB" ) {
               printf SMFN  "\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempObject2;
            } else {
               printf SMFN  "\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $packageWorkLogicalLibrary, $tempObject2;
            }

            # for debug, I think...
            $processedFileArray{$tempObject2} = "make_sim_makefile problem!!";
            $tempPackageTarget = "\${" . $packageWorkDirPath . "}/$tempPackageUpper" . "__.\${SIM_EXTENTION}";
            push(@processedPackageList, $tempPackageTarget);
         }
      }

      # Write a target for all the packages...
      printf SMFN  "\n\# \n";
      printf SMFN  "\# Target: all the packages\n";
      printf SMFN  "all_packages : ";      
      foreach $tempObject ( @processedPackageList ) {
	 printf SMFN  " \\\n";
	 printf SMFN  "  %s", $tempObject;
      }
      printf SMFN  "\n\n";
      
   }
   
   #
   # Now, do the Design Units part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the ordinal of this entity
         $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
         
         # Get the configuration and arch for this entity
         $tempEnt = $tempObject1;
         $tempConfig = $MERGE_CList[$tempOrdinal];
         $tempArch = $MERGE_AList[$tempOrdinal];
         
         # Get the kids, files and packages for this entity and make some lists
         $tempKids = $MERGE_KList[$tempOrdinal];
         $tempFiles = $MERGE_FList[$tempOrdinal];
         $tempPackages = $MERGE_PackageList[$tempOrdinal];
         @tempKidList = split( " ", $tempKids);
         @tempFileList = split( " ", $tempFiles);
         @tempPackageList = split( " ", $tempPackages);

         # Pull the files for each part of the design unit
         $tempConfigFile = $MERGE_Ent_2_ConfigFile{ $tempEnt };
         $tempArchFile = $MERGE_Ent_2_ArchFile{ $tempEnt };
         $tempEntFile = $MERGE_Ent_2_EntFile{ $tempEnt };
         
         # Count the number of files needed to make this design...
         $number_of_files = 0;
         foreach $tempErik ( @tempFileList ) {
            $number_of_files++;
         }

         # Print some header info into the makefile itself
         if ( $tempConfig == -1 ) {
            $tempTargetString = "entity(arch) \"$tempEnt\($tempArch\)\"";
         } else {
            $tempTargetString = "explicit configuration \"$tempConfig\"";
         }
         printf SMFN  "\n\# \n";
         printf SMFN  "\# \n";
         printf SMFN  "\# Target: %s\n", $tempTargetString;
         printf SMFN  "\# \n";
                     
         #
         # This needs to be improved to become automatically set...
         #
         # We should know where the files are
         
         # turned off until the /home/erik/souve.vhd is fixed for real
         #$sourceFileDirPath = ".";
         
         # We should be able to tell what logical library they are expected to be found
         $sourceWorkLogicalLibrary = "WORK";
         # and where it is mapped to.
         $sourceWorkDirPath = "WORK_DIR_PATH";

         # Now, build the targets for the design units.
         #
         # There are six different cases:
         #    1) Three files : Each part has it's own file, target the config
         #    2) Two files   : The entity and arch are in one file, the config in another, target the config
         #    3) Two files   : The arch and config are in one file, the entity in another, target the config
         #    4) Two files   : The entity and arch are in one file, there is no config, target the arch
         #    5) One file    : The entity and arch are in one file, there is no config, target the arch
         #    6) One file    : The entity, arch, and config are in one file, target the config
         
         if ( $number_of_files == 3 ) {

            # This is case 1
            
            # first do the entity
            #    This only depends on the source code and the packages
            #
            printf SMFN  "\#         Entity part in file \"%s\"\n", $tempEntFile;
            printf SMFN  "\# \n";

            # Build the entity target, save it for later, than print it.
            $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . ".\${SIM_EXTENTION}";
            push ( @designUnitTargets, $tempTarget );
            printf SMFN  "%s : \\\n", $tempTarget;
           
           # printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
            printf SMFN  "  %s ",  $tempEntFile;

            # if there are used packages, put them in too, 
            &SMFN_PrintPackagePrereqs($tempOrdinal, "E", SMFN);
            
            # print the action line
            if ( $sourceWorkLogicalLibrary eq "WORK" ) {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
            } else {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
            }
            
            #
            # Now do the architecture part
            #    This depends on the source code, kid, packages, and entity .sim file
            #
            printf SMFN  "\#         Arch part in file \"%s\"\n", $tempArchFile;
            printf SMFN  "\# \n";

            # Build the arch target, save it for later, than print it.
            $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempObject1 . "__" . $tempArch . ".\${SIM_EXTENTION}";
            push ( @designUnitTargets, $tempTarget );
            printf SMFN  "%s : \\\n", $tempTarget;
            
            # Put in the source code dependancy
            #printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempArchFile;
            printf SMFN  "  %s ",  $tempArchFile;
            
            # Put in the ENTITY dependancy
            printf SMFN  "\\\n";
            printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt;

            # if the are kids, put them in too
            &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

            # if there are used packages, put them in too, 
            &SMFN_PrintPackagePrereqs($tempOrdinal, "A", SMFN);
            
            # print the action line
            if ( $sourceWorkLogicalLibrary eq "WORK" ) {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempArchFile;
            } else {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempArchFile;
            }
            
            #
            # Finally do the config part
            #    This depends on the source code, packages, and entity and arch .sim files
            #
            printf SMFN  "\#         Configuration part in file \"%s\"\n", $tempConfigFile;
            printf SMFN  "\# \n";

            # save for later...
            $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempConfig . ".\${SIM_EXTENTION}";
            push ( @designUnitTargets, $tempTarget );
            printf SMFN  "%s : \\\n", $tempTarget;
       #     printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempConfigFile;
            printf SMFN  "  %s ", $tempConfigFile;
                        
            # Put in the ENTITY line
            printf SMFN  "\\\n";
            printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt;
                        
            # Put in the ARCH line
            printf SMFN  "\\\n";
            printf SMFN  "  \${%s}/%s__%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt, $tempArch;

            # if the are kids, put them in too  NOT FOR NOW 6/17/97
            # Does this make sense?  Shouldn't have these been checked already by the arch?
            # &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

            # if there are used packages, put them in too, 
            &SMFN_PrintPackagePrereqs($tempOrdinal, "C", SMFN);
            
            # print the action line
            if ( $sourceWorkLogicalLibrary eq "WORK" ) {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempConfigFile;
            } else {
               printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempConfigFile;
            }
            
         } elsif ( $number_of_files == 2  ) {

            printf SMFN  "\#         This design consists of two source files \n";
            printf SMFN  "\# \n";
            if ( ($tempConfigFile eq $tempArchFile) && ($tempConfig != 1) ) {
               
               # This is case 3
               
               # first do the entity
               printf SMFN  "\#         Entity part is in file \"%s\"\n", $tempEntFile;
               printf SMFN  "\# \n";

               # Build the entity target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;
        #       printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
               printf SMFN  "  %s ", $tempEntFile;

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "E", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
               }

               printf SMFN  "\#         Configuration and architecture parts are in file \"%s\"\n", $tempConfigFile;
               printf SMFN  "\# \n";

               # Build the configuration target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempConfig . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;
       #        printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempConfigFile;
               printf SMFN  "  %s ",  $tempConfigFile;

               # Put in the ENTITY line
               printf SMFN  "\\\n";
               printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "C", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempConfigFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempConfigFile;
               }

            } elsif ( ($tempEntFile eq $tempArchFile ) && ($tempConfig != 1) )  {
            
               # This is case 2
               
               # do the combined ent/arch target into the ent
               printf SMFN  "\#         entity and arch parts are in file \"%s\" \n", $tempEntFile;
               printf SMFN  "\# \n";
               
               # Build the arch target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . "__" . $tempArch . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;

               # print the source file dependancy line
        #       printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
               printf SMFN  "  %s ",  $tempEntFile;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "M", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
               }

               # Now do the explicit configuration target
               printf SMFN  "\#         Configuration part is in file \"%s\" \n", $tempConfigFile;
               printf SMFN  "\# \n";

               # Build the config target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempConfig . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;
          #     printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempConfigFile;
               printf SMFN  "  %s ",  $tempConfigFile;

               # Put in the ENTITY line
               printf SMFN  "\\\n";
               printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt;

               # Put in the ARCH line
               printf SMFN  "\\\n";
               printf SMFN  "  \${%s}/%s__%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempEnt, $tempArch;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "C", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempConfigFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempConfigFile;
               }
               
            } elsif ( ($tempEntFile eq $tempConfigFile)  && ($tempConfig != -1)) {
            
               # this isn't legal I think...
               printf SMFN  "\#         entity and config parts are in file \"%s\"\n", $tempEntFile;
               printf SMFN  "\#         arch only file \"%s\"\n", $tempArchFile;
               printf SMFN  "\#         THIS IS LEGAL!?!!? \n";
               
            } elsif ( $tempConfig == -1  ) {
            
               # This is case 4
               
               # first do the entity
               printf SMFN  "\#         Entity part is in file \"%s\"\n", $tempEntFile;
               printf SMFN  "\# \n";

               # Build the entity target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;
     #          printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
               printf SMFN  "  %s ",  $tempEntFile;

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "E", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
               }

               # Now do the Arch part and make it dependant on any kids
               printf SMFN  "\#         Arch part in file \"%s\"\n", $tempArchFile;
               printf SMFN  "\# \n";

               # Build the arch target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . "__" . $tempArch . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;
       #        printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempArchFile;
               printf SMFN  "  %s ",  $tempArchFile;

               # Put in the ENTITY line
               printf SMFN  "\\\n";
               printf SMFN  "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempObject1;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too,               
               &SMFN_PrintPackagePrereqs($tempOrdinal, "A", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempArchFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempArchFile;
               }
            }
         } else {
         
            if ( $tempConfig == -1 ) {
               
               # This is case 5
            
               printf SMFN     "\#         entity and arch parts in file \"%s\"\n", $tempEntFile;

               # print the target line, in this case it only needs to be the arch , the entity will be automatic

               # Build the arch target, save it for later, than print it.
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempEnt . "__" . $tempArch . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;

               # print the source file dependancy line
       #        printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
               printf SMFN  "  %s ",  $tempEntFile;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "M", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
               }
            } else {
            
               # This is case 6
               
               printf SMFN     "\#         entity and arch and config parts in file \"%s\"\n", $tempEntFile;

               # print the target line, in this case it only is the config, the entity and arch are automatic

               # Create the target, save for later, then print it...
               $tempTarget = "\${" . $sourceWorkDirPath . "}/" . $tempConfig . ".\${SIM_EXTENTION}";
               push ( @designUnitTargets, $tempTarget );
               printf SMFN  "%s : \\\n", $tempTarget;

               # print the source file dependancy line
       #        printf SMFN  "  %s/%s ", $sourceFileDirPath, $tempEntFile;
               printf SMFN  "  %s ", $tempEntFile;

               # if the are kids, put them in too
               &SMFN_PrintMyKids($tempOrdinal, SMFN, $sourceWorkDirPath);

               # if there are used packages, put them in too, 
               &SMFN_PrintPackagePrereqs($tempOrdinal, "M", SMFN);

               # print the action line
               if ( $sourceWorkLogicalLibrary eq "WORK" ) {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} %s \n", $tempEntFile;
               } else {
        	  printf SMFN  "\n\t\${ANALYZE_COMMAND} \${ANALYZE_OPTIONS} -w \${%s} %s \n", $sourceWorkLogicalLibrary, $tempEntFile;
               }
            }
         }
         printf SMFN  "\n";
      }
   }

   # Write a target for all the design units...
   printf SMFN  "\n\# \n";
   printf SMFN  "\# Target: all the design units\n";
   printf SMFN  "all_designUnits : ";      
   foreach $tempObject ( @designUnitTargets ) {
      printf SMFN  " \\\n";
      printf SMFN  "  %s", $tempObject;
   }
   printf SMFN  "\n\n";

   close SMFN;
}

sub SMFN_PrintPackagePrereqs {
###########
#
# used by make_sim_makefile
#
#  GLOBALS
#     @orderedPackageList
#     $write_packages
#     $packageName_2_LibraryName
#     $MPPackageName_2_MPCounter
#     $MP_FList
#     $MERGE_PackageList
#        $MERGE_ordinal_2_ent_MDAordinal{ $MERGE_counter }
#        $MERGE_ordinal_2_arch_MDAordinal{ $MERGE_counter }
#        $MERGE_ordinal_2_config_MDAordinal{ $MERGE_counter }
###########
   local ( $localOrdinal );
   local ( $localMDAOrdinal );
   local ( $localDesignPart );
   local ( $fileHandle );
   local ( $tempPackages );
   local ( @tempPackageList );
   local ( $foundTempPackage );
   local ( $packageWorkDirPath );
   local ( $tempObject1 );
   local ( $tempPackage2 );
   local ( $tempPackage );
   local ( $tempPackageUpper );
   local ( @usedPackageList );
   local ( $FileHandle );
   
   $localOrdinal = $_[0];
   $localDesignPart = $_[1];
   $FileHandle = $_[2];

   # make a list
   if ( $localDesignPart eq "E" ) {
      $localMDAOrdinal = $MERGE_ordinal_2_ent_MDAordinal{ $localOrdinal } ;
      $tempPackages = $UPackage_list[$localMDAOrdinal];
   } elsif ( $localDesignPart eq "A" ) {
      $localMDAOrdinal = $MERGE_ordinal_2_arch_MDAordinal{ $localOrdinal } ;
      $tempPackages = $UPackage_list[$localMDAOrdinal];
   } elsif ( $localDesignPart eq "C" ) {
      $localMDAOrdinal = $MERGE_ordinal_2_config_MDAordinal{ $localOrdinal } ;
      $tempPackages = $UPackage_list[$localMDAOrdinal];
   } elsif ( $localDesignPart eq "M" ) {
      $tempPackages = $MERGE_PackageList[$localOrdinal];
   } else {
      $tempPackages = "";
   }
   
   #printf STDOUT "GPP: The merged package string is \"%s\" \n", $tempPackages;
   
   @tempPackageList = split( " ", $tempPackages);

   if ( ($tempPackages ne "") && ($write_packages == 1) ) {
      foreach $tempPackage ( @tempPackageList ) { 
	 # only the parsed ones
	 $foundTempPackage = 0;
	 foreach $tempPackage2 (@orderedPackageList) {
	   if ($tempPackage2 eq $tempPackage ) {
              $foundTempPackage = 1;
              last;
	   }
	 }

	 if ( $foundTempPackage == 1 ) {
            $tempPackageUpper = "\U$tempPackage";
            push( @usedPackageList, $tempPackageUpper );
	 }
      }
   }
#   foreach $fileHandle ( @usedPackageList ) {
#      printf STDOUT "GPP: Found used package \"%s\" \n", $fileHandle;
#   }

        	  if ($packageName_2_LibraryName{$upperCaseTempKid} eq "WORK" ) {
        	     $tempPackageWorkLogicalLibrary = "WORK_DIR_PATH"; 
        	  } else {
        	     $tempPackageWorkLogicalLibrary = $packageName_2_LibraryName{$upperCaseTempKid} . "_WORK_DIR_PATH"; 
        	  }


   foreach $usedPackage ( @usedPackageList ) {
         if ($packageName_2_LibraryName{$usedPackage} eq "WORK" ) {
            $tempPackageWorkLogicalLibrary = "WORK_DIR_PATH"; 
         } else {
            $tempPackageWorkLogicalLibrary = $packageName_2_LibraryName{$usedPackage} . "_WORK_DIR_PATH"; 
         }
         printf $FileHandle "\\\n";
         printf $FileHandle "  \${%s}/%s.\${SIM_EXTENTION} ", $tempPackageWorkLogicalLibrary, $usedPackage;
   }
}

sub SMFN_PrintMyKids {
   local ($ordinal) = $_[0];
   local ($FileHandle) = $_[1];
   local ($sourceWorkDirPath) = $_[2];
   local ($tempKid);
   local ($newTempKid);
   local ($kidCounter);
   local ($tempKidOrdinal);
   local ($tempKidArch);
   local (@newTempKidList);

   if ( $MERGE_KList[$ordinal] ne "" ) {
      $kidCounter = 0;

      foreach $tempKid ( split( " ", $MERGE_KList[$ordinal]) ) { 
	 printf $FileHandle "\\\n";
	 if ( $tempKid != -1 ) {
            printf $FileHandle "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $tempKid;
	 } else {
            # Do we do the ent and arch for implicit configs or just the ent? For now BOTH
            # Get the child entity and arch names
            @newTempKidList = split( " ", $MERGE_IList[$tempOrdinal]);
            $newTempKid = $newTempKidList[$kidCounter];
            $tempKidOrdinal = $MERGE_entity_2_ordinal{ $newTempKid };
            $tempKidArch = $MERGE_AList[$tempKidOrdinal];
            printf $FileHandle "  \${%s}/%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $newTempKid;
            printf $FileHandle "\\\n";
            printf $FileHandle  "  \${%s}/%s__%s.\${SIM_EXTENTION} ", $sourceWorkDirPath, $newTempKid, $tempKidArch;
	 }
	 $kidCounter++;
      }
   }
}

sub derive_hier {
###########
#
# This fills the topDesignList with target designs
#
###########

   local ($counter1);
   
   # If a merged Unit has no parents, it is a top design...
   for ($counter1 = 0; $counter1 < $MERGE_counter; $counter1++ ) {

# BUG Look out for implicit Kids here
      if ( $MERGE_PList[$counter1] eq "" ) {
         push( @topDesignList, $MERGE_EList[$counter1]);
      }
   }
}

sub make_clean_parent_list {
###########
#
# This will return a string containing only the parent entitys in this
# design hierarchy
#
###########
   local ($tempObject3);
   local ($tempObject4);
   local ($tempOrdinal);
   local ($tempConfigName);
   local (@parentList);
   local ($cleanParentString);
   local ($oldParentString);

   $oldParentString = $_[0];
   
   printf STDOUT "MCPL: The old parent string is %s\n", $oldParentString if $MCPL_tells_all;
   @parentList = split(" ", $oldParentString);
   $cleanParentString = "";
   foreach $tempObject3 ( @parentList ) {
      foreach $tempObject4 ( @bottomFirstList ) {
         printf STDOUT "MCPL: Comparing parent value %s to list value %s\n", $tempObject3, $tempObject4 
                       if $MCPL_tells_all;
	 # convert the entity name to its configuration name
	 $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject4 };

#BUG## MUST DETECT THE NEGATIVE 1 "implicit config" condition HERE
	 $tempConfigName = $MERGE_CList[$tempOrdinal];
	 if ( $tempObject3 eq $tempConfigName ) {
	    $cleanParentString = $tempObject3 . " " . $cleanParentString ;
	    printf STDOUT "MCPL: Match found, cleanParentString is now %s\n", $cleanParentString if $MCPL_tells_all;

	    last;
	 }
      }
   }
   
   printf STDOUT "MCPL: Done, returning cleanParentString as %s\n", $cleanParentString if $MCPL_tells_all;
   return( $cleanParentString );

}


sub make_VHDL_SHF2_file {
###########
#
# Create the Standard Hierarchy Format v2 for DesignSurfer2
#
###########
   local ($localGraphFileName );
   
   $localGraphFileName_root = $_[0] . ".shf";
   $localGraphFileName = $outputDirectory . $localGraphFileName_root;
   # put this in the removal list
   push( @filesToCleanList, $localGraphFileName );
   
   # Save the SHF file in the list of all the SHF files
   push( @SHFFiles, $localGraphFileName );

   if ( !open(SHF, ">$localGraphFileName") )  {
      "HierachySurfer/MVS2F: Can't open the SHF file \"$localGraphFileName\" for output!\n";
      return;
   }
  
   printf SHF "\# Standard Hierarchy Format v2.0 file \n";  
   printf SHF "\# Spewed forth from HS(%s)!\n\n", $version;  
   printf SHF "set DSArray(surfDir) %s \n", $surfDir;  
   printf SHF "set DSArray(surfDate) \"%s\" \n", $surfDate;  
   printf SHF "set HSList {%s} \n", $SHF2_string;  
   $entityNotInList = 1;

   close SHF;
}

sub make_DC_script {
###########
#
# Make an analyze/elaborate script...
#
#  By default, only the top level entity is elab'ed
#
###########
   local ($localDCFilename);
   local ($tempObject1);
   local ($tempObject2);
   local ($tempPackage);
   local ($tempEntity);
   local ($targetLibrary);
   local ($tempString);
   local ($tempOrdinal);
   local ($tempOutputFileName);
   local ($entityNotInList);
   local (@tempList);
   local (@processedEntityList);
   local ($lastOne);
   local (%processedFileArray);

   $localDCFilename_root = $_[0];
   $localDCFilename = $outputDirectory . $localDCFilename_root;
   # put this in the removal list
   push( @filesToCleanList, $localDCFilename );

   if ( !open(DC, ">$localDCFilename") )  {
      "HierachySurfer/MVS2F: Can't open the DC file \"$localDCFilename\" for output!\n";
      return;
   }

   # Print standard crap   
   printf DC "/*  \n";
   printf DC "   Design Compiler analyze/elaborate script. \n";
   printf DC "   automagically generated from HierarchySurfer %s \n\n", $version;
   printf DC "\n   The following lines contain script defaults  \n";
   printf DC "   dc_file_path : The directory to put the elaborated \".db\" files \n";
   printf DC "   library_path : The directory to store the analyzed files \n";
   printf DC "*/ \n";
   printf DC "\ndc_file_path = \".\" \n";
   printf DC "library_path = \".\" \n";
   printf DC "\ndefine_design_lib WORK -path library_path\n";

   # print out the search_path include the source dirs, needed for 'include files 
   printf DC "\nsearch_path = search_path + {\\\n";
   foreach $source_dir ( @source_dir_list ) {
      printf DC "  %s \\\n",   $source_dir;
   }
   printf DC "}\n";

   # if turned on, write the packages
   if ($write_packages == 1 ) {
      printf DC  "\n";
      printf DC  "/* Analyze the packages */ \n";
      foreach $tempPackage (@orderedPackageList) {
         $tempPackageUpper = "\U$tempPackage";
         $targetLibrary = $packageName_2_LibraryName{$tempPackageUpper};
         $tempObject1 = $MPPackageName_2_MPCounter{$tempPackage};
         $tempString = $MP_FList[$tempObject1];

         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
                printf DC  "analyze -w %s -f vhdl %s\n", $targetLibrary, $tempObject2;
               $processedFileArray{$tempObject2} = "make_HDLA_script problem!!";
            } 
         } 
      }
   }
   printf DC  "\n";
   printf DC  "/* Analyze the design units */ \n";

   $entityNotInList = 1;
     
   # First, write the analyze part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
         $tempString = $MERGE_FList[ $tempOrdinal ];
      
         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
                printf DC  "analyze -w WORK -f vhdl %s\n", $tempObject2;
               $processedFileArray{$tempObject2} = "make_DC_script problem!!";
            } 
         }
          
         if ( $elab_each_unit == 1) {
            # Now elaborate and save
            printf DC "elaborate -w WORK %s\n", $MERGE_ETNList[$tempOrdinal];
            printf DC "dc_elab_file = dc_file_path + \"/\" + \"%s\" + .db\n", $MERGE_ETNList[$tempOrdinal];
            printf DC "write -output dc_elab_file\n\n";
         }
         $lastOne = $tempObject1;
      }
   }

   # This should get the top unit...
   if ($elab_each_unit == 0) {
      $tempOrdinal = $MERGE_entity_2_ordinal{ $lastOne };
      printf DC "\n/* Elaborate the top unit only */\n";
      printf DC "elaborate -w WORK %s\n", $MERGE_ETNList[$tempOrdinal];
      printf DC "dc_elab_file = dc_file_path + \"/\" + \"%s\" + .db\n", $MERGE_ETNList[$tempOrdinal];
      printf DC "write -h -output dc_elab_file\n\n";
   }
   
   printf DC "quit\n";
   close DC;
}

sub make_VSS_script {
###########
#
# Create the VSS analyze scripts
#
###########
   local ($localVSSFilename);
   local ($tempObject1);
   local ($tempObject2);
   local ($tempEntity);
   local ($tempString);
   local ($tempOrdinal);
   local ($entityNotInList);
   local (@tempList);
   local ($tempPackage);
   local (@processedEntityList);
   local (%processedFileArray);

   $localVSSFilename_root = $_[0];
   $localVSSFilename = $outputDirectory . $localVSSFilename_root;
   # put this in the removal list
   push( @filesToCleanList, $localVSSFilename );

   if ( !open(VSS, ">$localVSSFilename") )  {
      "HierachySurfer/MVS: Can't open the VSS file \"$localVSSFilename\" for output!\n";
      return;
   }

   $entityNotInList = 1;
   
   # Build a vhdlan file...
   printf VSS  "\#!/bin/csh -f -x\n";
   printf VSS  "\# Automagically generated vhdlan script from HierarchySurfer %s\n", $version;

   # if turned on, write the packages
   if ($write_packages == 1 ) {
       printf VSS  "\# Analyze the packages\n";
      foreach $tempPackage (@orderedPackageList) {
         $tempObject1 = $MPPackageName_2_MPCounter{$tempPackage};
         $tempString = $MP_FList[$tempObject1];

         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
                printf VSS  "vhdlan -nc %s\n", $tempObject2;
               $processedFileArray{$tempObject2} = "make_HDLA_script problem!!";
            } 
         } 
      }
   }

   printf VSS  "\n";
   printf VSS  "\# Analyze the design units\n";
  
   # Write the vhdlan part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
         $tempString = $MERGE_FList[ $tempOrdinal ];
      
         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
               printf VSS  "vhdlan -nc %s\n", $tempObject2;
               $processedFileArray{$tempObject2} = "make_VSS_script problem!!";
            } 
         } 
         printf VSS  "\n";
      }
   }
   close VSS;
   
   #Make the file executable
   chmod 0744, $localVSSFilename;
}

sub make_Cy_script {
#################
#
# Create the Cyan and Cylab scripts...
#
#################
   local ($localCyanFilename);
   local ($localCylabFilename);
   local ($tempObject1);
   local ($tempObject2);
   local ($topObject);
   local ($tempEntity);
   local ($tempString);
   local ($tempOrdinal);
   local ($entityNotInList);
   local (@tempList);
   local (@processedEntityList);
   local ($tempPackage);
   local (%processedFileArray);

   $entityNotInList = 1;

   $localCyanFilename_root = $_[0];
   $localCyanFilename = $outputDirectory . $localCyanFilename_root;
   # put this in the removal list
   push( @filesToCleanList, $localCyanFilename );

   if ( !open(CYAN, ">$localCyanFilename") )  {
      "HierachySurfer/MCS: Can't open the CYAN file \"$localCyanFilename\" for output!\n";
      return;
   }

   $localCylabFilename_root = $_[1];
   $localCylabFilename = $outputDirectory . $localCylabFilename_root;
   # put this in the removal list
   push( @filesToCleanList, $localCylabFilename );

   if ( !open(CYLAB, ">$localCylabFilename") )  {
      "HierachySurfer/MCS: Can't open the CYLAB file \"$localCylabFilename\" for output!\n";
      return;
   }

   printf CYAN  "\#!/bin/csh -f -x\n";
   printf CYAN  "\# Automagically generated cyan script from HierarchySurfer! %s\n", $version ;
   printf CYLAB  "\#!/bin/csh -f -x\n";
   printf CYLAB  "\# Automagically generated cylab script from HierarchySurfer! %s\n", $version;
  
   # if turned on, write the packages
   if ($write_packages == 1 ) {
      printf CYAN  "\n";
      printf CYAN  "\# Analyze the packages\n";
      foreach $tempPackage (@orderedPackageList) {
         $tempObject1 = $MPPackageName_2_MPCounter{$tempPackage};
         $tempString = $MP_FList[$tempObject1];

         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
               printf CYAN  "cyan %s\n", $tempObject2;
               $processedFileArray{$tempObject2} = "make_HDLA_script problem!!";
            } 
         } 
      }
   }
   printf CYAN  "\n";
   printf CYAN  "\# Analyze the design units\n";
  
   # Write the design units
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         $topObject = $tempObject1;
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
         $tempString = $MERGE_FList[ $tempOrdinal ];
      
         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
               printf CYAN  "cyan %s\n\n", $tempObject2;
               $processedFileArray{$tempObject2} = "make_VSS_script problem!!";
            } 
         } 
         if ( $elab_each_unit == 1) {

#BUG  MUST DETECT '-1' here for implicit config
             printf CYLAB "cylab %s\n\n", $MERGE_CList[ $tempOrdinal ];
         }
      }
   }

   # This should get the top unit...
   if ($elab_each_unit == 0) {
      $tempOrdinal = $MERGE_entity_2_ordinal{ $topObject };
      
#BUG  MUST DETECT '-1' here for implicit config
      printf CYLAB "cylab %s\n\n", $MERGE_CList[ $tempOrdinal ];
   }
   
   #Make the files executable
   chmod 0744, $localCyanFilename, $localCylabFilename;

   close CYAN;
   close CYLAB;
}

sub make_HDLA_script {
#################
#
# Will not break on case anymore, I think...
# Trying to enhance to combine files in case of multiple source files... 
# This is done to get around STAR 26393
#
# This also creates a list of combined files that the unit_report file spits out
#
#################
   local ($localHDLASetupFile);
   local ($localHDLAShellFile);
   local ($tempObject1);
   local ($tempObject2);
   local ($topObject);
   local ($analyzeFileName);
   local ($realTopEntity);
   local ($tempEntity);
   local ($tempString);
   local ($tempOrdinal);
   local ($tempOutputFileName);
   local ($entityNotInList);
   local (@tempList);
   local ($tempPackage);
   local ($upperCaseTempKid);
   local ($tempEN);
   local (@processedEntityList);
   local (%processedFileArray);
   
   
   @combinedFileList = ();
   
   $localHDLASetupFile_root = $_[0];
   $localHDLASetupFile = $outputDirectory . $localHDLASetupFile_root;
   # put this in the removal list
   push( @filesToCleanList, $localHDLASetupFile );

   if ( !open(HDLASU, ">$localHDLASetupFile") )  {
      "HierachySurfer/MCS: Can't open the HDLASU file \"$localHDLASetupFile\" for output!\n";
      return;
   }
   
   $localHDLAShellFile_root = $_[1];
   $localHDLAShellFile = $outputDirectory . $localHDLAShellFile_root;
   # put this in the removal list
   push( @filesToCleanList, $localHDLAShellFile );

   if ( !open(HDLASE, ">$localHDLAShellFile") )  {
      "HierachySurfer/MCS: Can't open the HDLASU file \"$localHDLAShellFile\" for output!\n";
      return;
   }

   # Print standard crap for the ha_shell file
   printf HDLASH "/* \n";
   printf HDLASH "   Ha_shell script, automagically generated from HierarchySurfer %s \n", $version;
   printf HDLASH "\n   The following lines contain script defaults  \n";
   printf HDLASH "   gtech_directory   : Directory for \".ha\", \".bi\", and \".id\" files \n";
   printf HDLASH "   library_directory : The physical location of logical library ADVISOR_LIB\n";
   printf HDLASH "*/\n";
   printf HDLASH "gtech_directory = \".\" \n";
   printf HDLASH "library_directory = \".\" \n";
   printf HDLASH "hdlin_advisor_directory = gtech_directory\n";
   printf HDLASH "define_design_lib ADVISOR_LIB -path library_directory\n";
   printf HDLASH "/* ADVISOR_LIB is not used anymore, everything is now mapped to work... */ \n";

   # if turned on, write the packages
   if ($write_packages == 1 ) {
      printf HDLASH  "\n";
      printf HDLASH  "/* Analyze the packages */ \n";
      foreach $tempPackage (@orderedPackageList) {
         $tempObject1 = $MPPackageName_2_MPCounter{$tempPackage};
         $tempString = $MP_FList[$tempObject1];
         $upperCaseTempKid = "\U$tempPackage";

         # For each file, write the lines...
         @tempList = split(" ", $tempString);
         foreach $tempObject2 ( @tempList ) {
            if ( !defined ( $processedFileArray{$tempObject2}) ) {
               printf HDLASH  "analyze -w %s -f vhdl %s\n", $packageName_2_LibraryName{$upperCaseTempKid}, $tempObject2;
               $processedFileArray{$tempObject2} = "make_HDLA_script problem!!";
            } 
         } 
      }
   }
   
   printf HDLASH  "\n";
   printf HDLASH  "\/* Analyze the design units */\n";

   # Get the name of the real name of the top entity
   $tempEN = "\U$top_entity";
   $tempOrdinal = $MERGE_entity_2_ordinal{ $tempEN };
   $realTopEntity = $MERGE_ETNList[ $tempOrdinal ];

   # Now, make a project (setup) file for this design...
   printf HDLASU "\# Created by HierarchySurfer %s \n\n", $version;
   printf HDLASU "\# -------------------------------------------------------------------- \n"; 
   printf HDLASU "\# 		 HDL Advisor Project File for design : \"%s\"  \n", $realTopEntity ;
   printf HDLASU "\# --------------------------------------------------------------------  \n";
   printf HDLASU "set  ha_handle_multiple_instances \" auto_uniquify \" \n";
   printf HDLASU "set  ha_top_design_name 	\" %s \" \n", $realTopEntity ;
   $tempOutputFileName = $realTopEntity . ".ha";
   printf HDLASU "set  ha_gtech_top_db_file 	\" %s \" \n", $tempOutputFileName ;

   # Print the source directories
   printf HDLASU "set  ha_search_path 	\" \\ \n" ;
   foreach $source_dir ( @source_dir_list ) {
      printf HDLASU "  %s \\ \n", $source_dir;
   }
   printf HDLASU "  \" \n";

   # Print the source directories
   printf HDLASU "set  ha_gtech_db_files  \"  \\ \n" ;

   $entityNotInList = 1;
     
   # First, write the ha_shell part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         $topObject = $tempObject1;
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
         $tempString = $MERGE_FList[ $tempOrdinal ];
      
         # If this unit is composed of more than one file, slap them into an concated file
         @tempList = split(" ", $tempString);
         if ( $#tempList > 0 ) {
            $analyzeFileName = $MERGE_ETNList[$tempOrdinal] . "_combined.cvhd";
            push(@combinedFileList, $analyzeFileName);
#            printf STDOUT "DUDE: For Advisor to work, I have to concatenate all the source files for entity \"%s\"\n", $MERGE_ETNList[$tempOrdinal];
#            printf STDOUT "into a new file \"%s\"\n", $analyzeFileName;
            open (ANALYZEOUT, ">$analyzeFileName");

	    # put this in the removal list
	    push( @filesToCleanList, $analyzeFileName);

            foreach $tempObject2 ( @tempList ) {
               open ( TEMP, $tempObject2 );
               while (<TEMP>) {
                  print ANALYZEOUT;
               }
               close TEMP;
            }
            close ANALYZEOUT;
         } else { 
            $analyzeFileName = $tempString;
         }
         if ( !defined ( $processedFileArray{$analyzeFileName}) ) {
            printf HDLASH  "analyze -w WORK -f vhdl %s\n", $analyzeFileName;
            $processedFileArray{$analyzeFileName} = "make_HDLA_script problem!!";
         } 

         if ( $elab_each_unit == 1) {
            # Now elaborate and save
            printf HDLASH "elaborate -w WORK %s\n", $MERGE_ETNList[$tempOrdinal];
            printf HDLASH "advisor_output_file = gtech_directory + \"/\" + \"%s\" + .ha\n", $MERGE_ETNList[$tempOrdinal];
            printf HDLASH "write -output advisor_output_file\n\n";
            $tempOutputFileName = $MERGE_ETNList[$tempOrdinal] . ".ha";
            printf HDLASU "  %s \\ \n", $tempOutputFileName;
         }
      }
   }

  if ( $elab_each_unit == 0) {
     # First, elaborate the top design
     $tempOrdinal = $MERGE_entity_2_ordinal{ $topObject };
     printf HDLASH "\n/* elaborate from the top design */\n";
     printf HDLASH "elaborate -w WORK %s\n", $MERGE_ETNList[$tempOrdinal];
     printf HDLASH "\nuniquify\n";

     printf HDLASH "\n/* Save all the designs into the gtech_directory */\n";
     printf HDLASH "advisor_output_file = gtech_directory + \"/\" + \"%s\" + .ha\n", $MERGE_ETNList[$tempOrdinal];
     printf HDLASH "write -h -output advisor_output_file\n\n";
     
     $tempOutputFileName = $MERGE_ETNList[$tempOrdinal] . ".ha";
     printf HDLASU "  %s \\ \n", $tempOutputFileName;

     # Now, save all the designs into the gtech_directory
#     printf HDLASH "\n/* Save all the designs into the gtech_directory */\n";
#     foreach $tempObject1 (@processedEntityList ) {
#        $tempOrdinal = $MERGE_entity_2_ordinal{ $tempObject1 };
#	printf HDLASH "current_design %s\n", $MERGE_ETNList[$tempOrdinal];
#	printf HDLASH "advisor_output_file = gtech_directory + \"/\" + \"%s\" + .ha\n", $MERGE_ETNList[$tempOrdinal];
#	printf HDLASH "write -output advisor_output_file\n\n";
#	$tempOutputFileName = $MERGE_ETNList[$tempOrdinal] . ".ha";
#	printf HDLASU "  %s \\ \n", $tempOutputFileName;
#     }
  }
 
   printf HDLASH "quit\n";
   close HDLASH;

   printf HDLASU "  \" \n";
  

   close HDLASU;
}

sub build_package_hier {
#################
#
# Simply find all childern and parents for the list of packages
#
#  $MP_ParentList and ??t are set in this subroutine...
#
# This works on MK_list
# This uses MPCounter
#################
   local ($myKidString1);
   local ($myKidString2);
   local (@tempParentList);
   local ($tempOrd);
   local ($counter1);
   local ($counter2);
   local ($instFound);
   local ($kid);
   
   # for debugging...
   if ($BPH_tells_all == 1 ) {
      printf STDOUT "The values of the MP arrays are: \n";
      printf STDOUT "Ordinal   MP_PList    MP_KList    MP_FList\n";
      for ( $counter1 = 0; $counter1 < $MPCounter; $counter1++ ) {
         printf STDOUT "%d       %s        %s     %s\n", $counter1, $MP_PList[$counter1], $MP_KList[$counter1], $MP_FList[$counter1];
      }
   }

   #
   # Basically look thru the list of all merged packages
   # to see if you are used by the package
   # if so push that package into tempParentList
   # clean the list and set MP_ParentList to that clean value
   #
   for ( $counter1 = 0; $counter1 < $MPCounter; $counter1++ ) {
      @tempParentList = ();
      $tempPackage1 = $MP_PList[$counter1];
      printf STDOUT "\nBPH:  Building parent list for package \"%s\"\n", $tempPackage1 if $BPH_tells_all;
      for ( $counter2 = 0; $counter2 < $MPCounter; $counter2++ ) {
         $tempPackage2 = $MP_KList[$counter2];
         @tempPackage2KidList = split(" ", $tempPackage2);
         printf STDOUT "      BPH: The value of MP_KList is \"%s\" \n", $MP_KList[$counter2] if $BPH_tells_all;
         foreach $tempPackage3 (@tempPackage2KidList) {
            printf STDOUT "      BPH: Comparing package \"%s\" to package \"%s\"\n", $tempPackage3, $tempPackage1 if $BPH_tells_all;
            if  ( ($tempPackage3 eq $tempPackage1) && ($counter2 != $counter1) ) {
               push( @tempParentList, $MP_PList[$counter2] );
            }
         }
      }
      $MP_ParentList[$counter1] = join(" ", @tempParentList); 
      printf STDOUT "BPH:  The packages that use \"%s\" are \"%s\"\n", $tempPackage1, $MP_ParentList[$counter1] if $BPH_tells_all;
   }
}

sub build_design_hier {
#################
#
# Simply find all childern and parents
# When I get around to resolving instances, that will go here...
#
#  $MERGE_KList and $MERGE_PList are set in this subroutine...
#
#   if ($MERGE_CList[$tempOrd] = -1)
#      MERGE_KList gets a ent__arch entry
#      MERGE_PList gets a ent__arch entry
#
#   05/02/97 : enhanced to track the number of missing kids and save the kid and the parent
#   05/12/97 : enhanced to handle implicit configurations with i.d. $MERGE_CList[$tempOrd] = -1
#
#################
      local ($myKidString1);
      local ($myKidString2);
      local (@archCompList);
      local ($tempOrd);
      local ($tempComp);
      local ($tempConfig);
      local ($instFound);
      local ($instancesMissingSource) = 0;
      local (@missingSourceList);
      local ($kid);
      local (%myMasterComponentList_2_string );

      # Build the kid list first, for each merged configuration
      # Save the configurations
      #
      printf STDOUT "\nBDH: Now building kid list\n" if $BDH_tells_all;
      for ($counter1 = 0; $counter1 < $MERGE_counter; $counter1++ ) {
         
         # remove the case dependancies
         $myKidString1 = "\U$MERGE_IList[$counter1]";
         @myKidList = split(" ", $myKidString1);
         @tempKidList = ();
         @missingKidList = ();
         %myMasterComponentList_2_string = ();
         foreach $kid (@myKidList){
            $instFound = 0;
            # Must do an entity to configuration mapping here
            
            #
            # Look to resolve components in three spots
            #   1) Resolve against the entities parsed
            #   2) Resolve against components declared in the arch
            #   3) Resolve against components declared in the used package
            
            # Must check if the kid is an entity at all!!! 6/18/96
            if ( defined( $MERGE_entity_2_ordinal{ $kid } ) ) {
               $tempOrd = $MERGE_entity_2_ordinal{ $kid };

               # Pack the list with the configurations of the kid entitys
               
               if ( $MERGE_CList[$tempOrd] == -1 ) {
                  # 
                  $tempConfig = $MERGE_EList[$tempOrd] . "__" . $MERGE_AList[$tempOrd];
               } else {
                  $tempConfig = $MERGE_CList[$tempOrd];
               }
               $masterKidList[$kidListCounter] = $tempConfig;
               $kidListCounter++;

               # and also into a temp list for later usage.
               
               push( @tempKidList, $tempConfig);
            
               $instFound = 1;
            } else {  
               #
               # Here is the spot where the dealing with non-entity kids should go...
               # First, look at the components declared in this architecture
               $myKidString2 = "\U$MERGE_ACList[$counter1]";
               @archCompList = split( " ", $myKidString2);
               foreach $tempComp (@archCompList) {
                  if ( $tempComp eq $kid ) {
                     $instFound = 1;
                  }
               }
               
               # Next, look at the components in the packages for which we have source
               #
               # 05/12/97: This needs to be tested...  Doesn't appear to work..
               #
               if ( $instFound == 0 ) {
                  # First figure out what packages are contained in the source
                  @myRawUsedPackages = split(" ", $MERGE_PackageList[$counter1]);
                  
                  # Then examine only those packages that have been parsed
                  @myRealUsedPackages = ();
                  foreach $tempComp ( @myRawUsedPackages ) {
                     if ( defined( $MPPackageName_2_MPCounter{$tempComp} ) ) {
                        push( @myRealUsedPackages, $tempComp);
                     }
                  }
                  
                  # Now gather all the components in those parse packages into a single array
                  foreach $tempComp ( @myRealUsedPackages ) {
                     $myMPOrdinal = $MPPackageName_2_MPCounter{$tempComp};
                     @archCompList = split(" ", $MP_CList[$myMPOrdinal]);
                     foreach $tempComp2 ( @archCompList ) {
                        $myMasterComponentList_2_string{$tempComp2} = "FOUND";
                     }
                  }
                 
                  # Finally, compare away...
                  if ( defined($myMasterComponentList_2_string{$kid}) ) {
                     $instFound = 1;
                  }
               } else {
                  # still not found, the save the info and report it later...
        	  $instancesMissingSource++;

        	  # save the kid and its parent here
        	  push(@missingSourceList, $kid);
        	  push(@missingSourceList, $MERGE_ETNList[$counter1]);
               }
            }
            
            if ( $instFound == 0 ) {
#               printf STDOUT "Warning:  I can't resolve reference \"%s\" of entity \"%s\". \n", $kid,
#               $MERGE_ETNList[$counter1];
#               printf STDOUT "          Not a big deal as long as it is contained in a declared package \n";
                push( @missingKidList, $kid);
            }
         }

         # Store the list of missing instances for later usage...
         $cleanMIAKidString = &make_uniq_list( join ( " ", @missingKidList) );
         $MERGE_MIAList[$counter1] = $cleanMIAKidString;
         
         # Tag the end of the master kid list for this entity
         $masterKidList[$kidListCounter] = "|";
         $kidListCounter++;
         
         # Now save the list of child configurations as a space joined string...
         $MERGE_KList[$counter1] = join ( " ", @tempKidList);
         printf STDOUT "BDH: My entity name is %s\n", $MERGE_EList[$counter1] if $BDH_tells_all;
         printf STDOUT "   BDH: My kids names are %s\n", $MERGE_IList[$counter1] if $BDH_tells_all;
         printf STDOUT "   BDH: My kids names configurations are %s\n", $MERGE_KList[$counter1] if $BDH_tells_all;
         printf STDOUT "   BDH: My missing kids names configurations are %s\n", $MERGE_MIAList[$counter1] if $BDH_tells_all;
      }
   
      #
      # Now, build the parent list for each merged configuration
      #
      @masterParentList = ();
      $parentListCounter = 0;
      for ($counter1 = 0; $counter1 < $MERGE_counter; $counter1++ ) {
         $MERGE_PPList[$counter1] = $parentListCounter;
         
         #
         # Look thru the entire list of kids to see who your parents(!) are...
         # Save the configurations...
         #
         $tempParentOrdCounter = 0;
         @tempParentList = ();
         for($counter2 = 0; $counter2 < $kidListCounter; $counter2++ ){

            # deal with implicit configs first
            if ( $MERGE_CList[$counter1] == -1 ) {
               $tempConfig = $MERGE_EList[$counter1] . "__" . $MERGE_AList[$counter1];
            } else {
               $tempConfig = $MERGE_CList[$counter1];
            }

            # If the element is a seperator, count it.
            # Now, use the seperator to tell what ordinal I belong to
            # Then pull that parent name from the EList.
            if ( $masterKidList[$counter2] eq "|" ) {
               # Walked over a boundary, inc the counter...
               $tempParentOrdCounter++;
               
            # If the configuration matches the kid...   
            } elsif ( $masterKidList[$counter2] eq $tempConfig ) {
            
               # Save the parent config into the parent list
               if ( $MERGE_CList[$tempParentOrdCounter] == -1 ) {
        	  $tempConfig = $MERGE_EList[$tempParentOrdCounter] . "__" . $MERGE_AList[$tempParentOrdCounter];
               } else {
        	  $tempConfig = $MERGE_CList[$tempParentOrdCounter];
               }

               $masterParentList[$parentListCounter] = $tempConfig;
               
               # and also into a temp list for later usage.
               push( @tempParentList, $tempConfig);
            }
         }
         
         # create a parent configuration string in the MERGE DB...
         $MERGE_PList[$counter1] = join ( " ", @tempParentList);
         $masterParentList[$parentListCounter] = "|";
         $parentListCounter++;
         printf STDOUT "BDH: My entity name is %s\n", $MERGE_EList[$counter1] if $BDH_tells_all;
         printf STDOUT "   BDH: My parents names are %s\n", $MERGE_PList[$counter1] if $BDH_tells_all;
      }
}

sub unclean_help {
###########
#
# Stupidly try to help the user, mostly broken however...
#
###########
   
   local ($tempMDAOrdinal);
   
   # Report why the design hierarchy can't be built and 
   # tell the user how to fix it
   printf STDOUT "\n      \"HierarchySurfer, please build the design hierarchy for me now.\"\n\n";
   printf STDOUT "\n      \"No way dude!\"\n\n\n";
   printf STDOUT "\nProblem:\n";
   printf STDOUT   "--------\n";
   printf STDOUT "This design hierarchy is not cool, so I am not going to create any script files!\n";
   printf STDOUT "\nReason:\n";
   printf STDOUT "-------\n";
   printf STDOUT "Like, I can't determine what entities and architectures belong together\n";
   printf STDOUT "Most of the time this means that you have more than one version of an\n";
   printf STDOUT "entity, or a couple architectures laying around for me to trip over!\n";
   printf STDOUT "\nBackground:\n";
   printf STDOUT   "-----------\n";
   printf STDOUT "The following configuration situations are legal for me:\n";
   printf STDOUT "\n  -Implicit: an entity with a SINGLE architecture and NO configurations\n";
   printf STDOUT "     The info below should list all architectures I detected for a given entity\n";
   printf STDOUT "     If the -w switch is set, I will write an explicit configuration for you,\n"; 
   printf STDOUT "     it will be in a file named IMPLICIT_CFG_ENT_ARCH.vhd.\n\n";
   printf STDOUT "  -Explicit: an entity with a SINGLE configuration\n";
   printf STDOUT "     The number of architectures is a don't care\n";
   printf STDOUT "\n";
   printf STDOUT "In any other mix of implicit and explicit configurations, I can't tell what  \n";
   printf STDOUT "configuration to choose, so I stop!  \n";
   printf STDOUT "\n";
   printf STDOUT "\nWhats next:\n";
   printf STDOUT   "-----------\n";
   printf STDOUT "To help you decide which configuration to use, I can write explicit files \n";
   printf STDOUT "for all the implicit configurations.  Also, I have reported these \"dirty\"\n";
   printf STDOUT "entities to you below.  Use the \"-w\" switch to get configurations out.\n\n";
   printf STDOUT "Another thing to be aware of is that if a entity/architecture pair appears\n";
   printf STDOUT "in more than one file, there is no way to resolve this with a configuration.\n";
   printf STDOUT "If there is an explicit configuration and more than one entity/architectures\n";
   printf STDOUT "that fit the bill, I will chose the first one that I find.\n";
   printf STDOUT "\n";
   printf STDOUT "So, now you know which entities need to have their configuration situation\n";
   printf STDOUT "straightened out.  To make this work, simply pick the desired configuration \n";
   printf STDOUT "they should be all explicit now.  Simply Move/Rename/Remove the other \n";
   printf STDOUT "configuration files so I can't see them and rerun me.  Remember to point to \n";
   printf STDOUT "where the new files are located.\n";
   printf STDOUT "\n";
   printf STDOUT "My counting of implicit/explicit is still a little screwed,\n";
   printf STDOUT "so just look at the listed files below\n";

   printf STDOUT "\nDirty Entities:\n";
   printf STDOUT "---------------\n";
   for ($tempEntityCounter = 0; $tempEntityCounter <= $#uncleanEList; $tempEntityCounter++ ) {
      $tempMDAOrdinal = $MERGEOrdinalToMDAOrdinal{$entity_name};
      printf STDOUT "\n   Entity \"%s\" from file %s:\n", $uncleanEList[$tempEntityCounter], $ECA_file_list[$tempMDAOrdinal];
      $newUncleanAString = $uncleanAList[$tempEntityCounter];
      @newUncleanAList   = split(' ', $newUncleanAString);
      $newUncleanFString = $uncleanFList[$tempEntityCounter];
      @newUncleanFList   = split(' ', $newUncleanFString);
      for ($counter10 = 0; $counter10 <= $#newUncleanAList; $counter10++) {
         printf STDOUT "      Architecture \"%s\" ", $newUncleanAList[$counter10];
         printf STDOUT " File \"%s\":\n", $newUncleanFList[$counter10];
      }
     
      # Look for overlapping entities
      for ($tempEntityCounter2 = 0; $tempEntityCounter2 <= $#uncleanEList; $tempEntityCounter2++ ) {
         $newUncleanFString = $uncleanFList[$tempEntityCounter2];
         @newUncleanFList   = split(' ', $newUncleanFString);
         if ( ($uncleanEList[$tempEntityCounter] eq $uncleanEList[$tempEntityCounter2]) && 
              ($tempEntityCounter2 != $tempEntityCounter) ) {
            printf STDOUT "      Detected an overlapping entitys in \n"; 
	    for ($counter10 = 0; $counter10 <= $#newUncleanFList; $counter10++) {
               printf STDOUT "         File \"%s\":\n", $newUncleanFList[$counter10];
	    }
         }
      }
      
   }
   
   # Look for overlapping entities
   for ($tempEntityCounter1 = 0; $tempEntityCounter1 <= $#uncleanEList; $tempEntityCounter1++ ) {
   }
}

sub make_uniq_list {
###########
#
# This subroutine takes a list of strings and returns it as ordered and uniq
#
###########

   local ( $token1 );
   local ( $token2 );
   local ( @newList1 );
   local ( @sortedList );
   local ( @cleanList );
   local ( $returnString );
   local ( $oldString );
   
   $oldString = $_[0];
   
   # make the string back into a list
   @newList1 = split(" ", $oldString);
   @sortedList = sort( @newList1 );
   
   $token2 = "";
   foreach $tempToken ( @sortedList ) {
      if ( $tempToken ne $token2 ) {
         push( @cleanList, $tempToken );
         $token2 = $tempToken
      }
   }

   return( join(" ", @cleanList) );

}

sub merge_packages {
###########
#
# Produce a merged listing of all the packages...
#
###########
   local ($tempPackageName);
   local ($tempPackageBody);
   local (@tempFileList);
   local (@tempKidPackageList);
   local ($pOrd);
   local ($pBOrd);
   local ($ordCounter);
   local ($tempString1);
   local ($tempString2);
   local ($design_component_number) = $ordinal_counter;

   printf STDOUT "MP: Into merge_package\n" if $MP_tells_all;
   # uniqing the string package_only would be a good idea...
   foreach $tempPackageName (@package_only) {
      printf STDOUT "   Working on package \"%s\"\n", $tempPackageName if $verbose_mode;
      
      @tempFileList = ();
      @tempKidPackageList = ();
      
      # First try to find where this package lives in the master lists
      # by plowing thru all the multi-D arrays
      printf STDOUT "MP: Looking for the target ordinal of the package \"%s\"\n", $tempPackageName if $MP_tells_all;
      for ( $ordCounter = 0; $ordCounter < $design_component_number; $ordCounter++) {
         printf STDOUT "   MP: The value of \"P_list[%s]\" is \"%s\"\n",$ordCounter, $P_list[$ordCounter] 
	                    if $MP_tells_all; 
	      
         #  find where the package is in the list and save that ordinal
         printf STDOUT "   MP: \"\$P_list[\$ordCounter]\" is \"%s\" \n", $P_list[$ordCounter] if $MP_tells_all;
         printf STDOUT "   MP: \$tempPackageName is \"%s\" \n", $tempPackageName if $MP_tells_all;
         $tempString1 = "\U$P_list[$ordCounter]";
         $tempString2 = "\U$tempPackageName";
         if ( $tempString1 eq $tempString2 ) { 
            $pOrd = $ordCounter;
            printf STDOUT "   MP: \$pOrd is \"%d\" \n", $pOrd if $MP_tells_all;
            printf STDOUT "   MP: \$ordCounter is \"%d\" \n", $ordCounter if $MP_tells_all;
            printf STDOUT "   MP: Package \"%s\" found at ordinal \"%s\"\n\n", $tempPackageName, $ordCounter 
                                  if $MP_tells_all; 
            last;
         }
      }
      printf STDOUT "   MP: \"\$pOrd\" is \"%d\" \n", $pOrd if $MP_tells_all;
      
      # Save the file that contains the Package (header) declaration into the temp file list...
      push( @tempFileList, $ECA_file_list[$pOrd]);
      printf STDOUT "   MP: Saving file \"%s\" that contains package header\n", $ECA_file_list[$pOrd] if $MP_tells_all;
      
      # To start with set the body ordinal equal to the package ordinal
      # If they are different, pBOrd will change below, this might not be a good idea if the body is not found...
      $pBOrd = $pOrd;
      
      # This will "mess up" if there are more than one package bodies...
      # Now, look thru the entire MDA and find any and all package bodies
      printf STDOUT "\n   MP: Now looking for any separate package bodies\n" if $MP_tells_all;
      for ( $ordCounter = 0; $ordCounter < $design_component_number; $ordCounter++) {
         # name == body but file not the same?
         printf STDOUT "   MP: Comparing \"%s\" to \"%s\" and \"%s\" to \"%s\"\n",$PB_list[$ordCounter], $tempPackageName,$ECA_file_list[$ordCounter], $ECA_file_list[$pOrd] if $MP_tells_all;

         # To be extra careful, make the comparison non-case sensitive...  9/27/97
         $tempPackageNameUpper = "\U$tempPackageName";
         $tempPB_listUpper = "\U$PB_list[$ordCounter]";
         if ( ($tempPB_listUpper eq $tempPackageNameUpper) && ($ECA_file_list[$ordCounter] ne $ECA_file_list[$pOrd])) {
            # Save the file names...
            push( @tempFileList, $ECA_file_list[$ordCounter]);
            printf STDOUT "   MP: Saving file \"%s\" that contains package body\n", $ECA_file_list[$ordCounter] if $MP_tells_all;
            $pBOrd = $ordCounter;
         }
      }
            
      # Now, finally, save the merged info into the MP_lists
      # Name
      $MP_PList[$MPCounter] = $tempPackageName;
      # Files
      $MP_FList[$MPCounter] = join(" ", @tempFileList);
      # Package Body files
      $MP_PBFList[$MPCounter] = $ECA_file_list[$pBOrd];
      # Components declared within
      $MP_PDFList[$MPCounter] = $ECA_file_list[$pOrd];
      # Components declared within
      $MP_CList[$MPCounter] = $PComponent_list[$pBOrd];
      
      # Save the kid packages for this package
      # why is this line here???
      push (@tempKidPackageList, $UPackage_list[$pOrd] );
      
      printf STDOUT "   MP: \"\$UPackage_list[\$pOrd]\" is \"%s\" \n", $UPackage_list[$pOrd] if $MP_tells_all;
      printf STDOUT "   MP: \"\$pBOrd\" is \"%d\", \"\$pOrd\" is \"%d\" \n", $pBOrd, $pOrd if $MP_tells_all;
      
      # If the body is in a different file 
      if ($pBOrd != $pOrd) {
         push (@tempKidPackageList, $UPackage_list[$pBOrd] );
      } 
      
      # Now make sure that each package is only listed once
      $MP_KList[$MPCounter] = &make_uniq_list( join(" ", @tempKidPackageList ));
      # finally, save it for later usage.
      printf STDOUT "   MP: The raw list of packages that package \"%s\" depends on is \"%s\"\n", $tempPackageName, join(" ", @tempKidPackageList ) if $MP_tells_all;
      printf STDOUT "   MP: The clean list of packages that package \"%s\" depends on is \"%s\"\n", $tempPackageName, $MP_KList[$MPCounter] if $MP_tells_all;
      
      printf STDOUT "   MP: MPCounter \"%d\", MP_PList \"%s\", MP_FList \"%s\" \n", $MPCounter, $MP_PList[$MPCounter], $MP_FList[$MPCounter] if $MP_tells_all;
      
      # associate the package name to the MPCounter
      $MPPackageName_2_MPCounter{$tempPackageName} = $MPCounter;
      
      printf MPDA "%s | %s | %s | %s | %s | %s \n",$MP_PList[$MPCounter], $MP_FList[$MPCounter],
      $MP_CList[$MPCounter], $MP_KList[$MPCounter], $MP_PBFList[$MPCounter], $MP_PDFList[$MPCounter];
      
      $MPCounter++;      
   }
   
   close MPDA;
}

sub merge {
###########
#
# This is the big kahuna!!
#
###########
   local ($temp_file) = "junk";
   local ($target_arch) = "";
   local ($ord_counter2) = 0;
   local ($ent_ord) = 0;
   local ($arch_ord) = 0;
   local ($config_ord) = 0;
   local ($config_ord_counter) = 0;
   local ($arch_ord_counter) = 0;
   local ($configuration_match) = 0;
   local ($design_component_number) = $ordinal_counter;
   local ($configClean) = 0;
   local ($tempPackageList);
   local ($tempLibraryList);
   local ($implicit_configurations) = 0;
   local ($explicit_configurations) = 0;      

   %entity_2_cfg_files = ();
   $MERGE_counter = 0;
   %MERGE_entity_2_ordinal = ();
   
   # track the merge ordinal to the MDA ordinals
   %MERGE_ordinal_2_ent_MDAordinal = ();
   %MERGE_ordinal_2_arch_MDAordinal = ();
   %MERGE_ordinal_2_config_MDAordinal = ();
         
   # Create a "merge" file for each entity in memory
   foreach $entity_name ( @entity_only) {

      printf STDOUT "--------------------------------------------------\n" if $M_tells_all; 
      printf STDOUT "   Working on Entity \"%s\"\n", $entityBogusNameToRealName{$entity_name} if $verbose_mode; 
      printf STDOUT "--------------------------------------------------\n" if $M_tells_all; 

      # Set the initial conditions
      $temp_file = "junk";
      $ord_counter2 = 0;
      $ent_ord = 0;
      $config_ord_counter = 0;
      $arch_ord_counter = 0;
      $configuration_match = 0;
      $implicit_configurations = 0;
      $explicit_configurations = 0;      
      @config_ord_list = ();
      @arch_ord_list = ();
      @DU_file_list = ();

      # First try to Find where this entity lives in the master lists
      # by plowing thru all the multi-D arrays
      printf STDOUT "MERGE: Looking for the target ordinal of the entity\n" if $M_tells_all;
      for ( $ord_counter2 = 0; $ord_counter2 < $design_component_number; $ord_counter2++) {
         printf STDOUT "   MERGE: The value of E_list[%s] is \"%s\"\n",$ord_counter2, $E_list[$ord_counter2] if $M_tells_all; 
	      
         #  find where the entity is in the list and save that ordinal
         if ( $E_list[$ord_counter2] eq $entity_name ) { 
            $ent_ord = $ord_counter2;
            printf STDOUT "   MERGE: Entity \"%s\" found at ordinal \"%s\"\n\n", $entity_name, $ord_counter2 if $M_tells_all; 
            last;
         }
      }

      # Now find if a configuration deals with this entity
      # If so, find the postion of the arch called out by the configuration
      # 
      # I need to find the total of unconfig'ed archs and configs
      #
      # This will find all the configurations of the entity and save them into a list
      
      $configuration_match =  0;
      printf STDOUT "\nMERGE: Looking for all explicit configurations of this entity\n" if $M_tells_all;
      for ( $ord_counter2 = 0; $ord_counter2 < $design_component_number; $ord_counter2++) {

         printf STDOUT "   MERGE: The value of CE_list[%s] is \"%s\"\n",$ord_counter2, $CE_list[$ord_counter2] if $M_tells_all; 

         # Try to match a configuration to the entity
         if ( $entity_name eq $CE_list[$ord_counter2] ) { 
            # Bump the number of matches
            $configuration_match++;

            # save the configuration
            $config_ord_list[$config_ord_counter] = $ord_counter2;

            # grab the architecture attached to this configuration
            $target_arch = $CA_list[$ord_counter2];

            #look for an arch that matches it and save its ord
            # Here I am assuming that there MUST be an architecture for the found configuration...
            # which is of course not correct!!!
            # If not, the arch_ord_list will have gaps in it...
            #
            $configArchNotFound = 1;
            for ( $ord_counter3 = 0; $ord_counter3 < $design_component_number; $ord_counter3++){
               printf STDOUT "      MERGE: Comparing Arch: \"%s\",  to target_arch: \"%s\" ", $A_list[$ord_counter3], $target_arch if $M_tells_all;
               printf STDOUT "and entity_name: \"%s\" to AE_list: \"%s\"\n", $entity_name,  $AE_list[$ord_counter3] if $M_tells_all;
               if ( ( $entity_name eq $AE_list[$ord_counter3] ) && ($target_arch eq $A_list[$ord_counter3] ) ) {
                  $arch_ord_list[$config_ord_counter] = $ord_counter3;
                  
                  # If the arch is bound by an explicit config, save the name of the config with the arch...
                  $AConfig_list[$ord_counter3] = $C_list[$ord_counter2];
	          printf STDOUT "      MERGE: Matched target arch \"%s\" to arch \"%s\" of config \"%s\" of entity \"%s\"\n\n", 
                          $target_arch, $A_list[$ord_counter3], $C_list[$ord_counter2], $entity_name if $M_tells_all;
                  $configArchNotFound = 0;
                  last;  
               }         
            }
            $config_ord_counter++;
         }
      }

      # find all architectures that match up with the entity AND are not bound with an configuration.     
      # Question: how do we figure out how to build the design with multiple
      # architectures?!?!?  
      # Answer: we build configuration files and ask the users to pick the one they want to use and run again!!
      #
      if ( $configuration_match == 0 ) {
         printf STDOUT "\nMERGE:   No explicit configurations found for entity: \"%s\"\n", $entity_name  if $M_tells_all; 
      }
      
      # Start the arch count where the config count left off...
      $arch_ord_counter = $config_ord_counter;

      # Go thru all the arch's entities and look for a match
      # This will put all the unbound architectures into the list arch_ord_list
      #
      printf STDOUT "\nMERGE: Looking for all implicit configurations of this entity\n" if $M_tells_all;
      for ( $ord_counter2 = 0; $ord_counter2 < $design_component_number; $ord_counter2++) {
	 printf STDOUT "   MERGE:   Comparing entity: \"%s\" to AE \"%s\", with AConfig_list = \"%s\"\n", $entity_name, 
	                   $AE_list[$ord_counter2], $AConfig_list[$ord_counter2] if $M_tells_all; 

         # If the uglies bump AND the arch is not already explicitly configured, then save the ordinal into the list...
#         if ( ($entity_name eq $AE_list[$ord_counter2]) && ($AConfig_list[$ord_counter2] eq "") ) { 
         if ( $entity_name eq $AE_list[$ord_counter2] ) { 
	        printf STDOUT "MERGE: Arch \"%s\" found at ordinal \"%s\" for entity: \"%s\"\n\n", 
	           $A_list[$ord_counter2], $ord_counter2, $entity_name if $M_tells_all; 
            $arch_ord_list[$arch_ord_counter] = $ord_counter2;
            $arch_ord_counter++;
         }
      }

      $implicit_configurations = $arch_ord_counter - $config_ord_counter;
      $explicit_configurations = $config_ord_counter;

      printf STDOUT "\nMERGE: Number of explicit configurations of entity \"%s\" is \"%s\"\n", $entity_name, 
                        $explicit_configurations if $M_tells_all;

      printf STDOUT "MERGE: Number of implicit configurations of entity \"%s\" is \"%s\"\n", $entity_name, 
                        $implicit_configurations if $M_tells_all;

      # Now that we know the exact number of implicit and explicit configurations, deal with them.
      # 
      # One of the following cases should be legal (clean hier)
      #    1 explicit configuration and multiple archs and not create the new config files for the unbound archs
      #    1 implicit (entity/arch) configuration only, I will create a config vhdl file (if requested?)
      #
      # All other cases are unclean and should be flagged and configuration vhdl files built, merge file will not
      
      # I am not yet sure if this is correct.... I now think it is... 5/18/96
      # if more than one explicit or more than one implicit without a single explicit, this is no good!
      if (($explicit_configurations > 1) || (($implicit_configurations > 1) && ($explicit_configurations == 0)) )  {
         #
         # Dirty entity!!!
         # Don't bother building a merge file...
         $configClean = 1;
         
         printf STDOUT "BUMMER! Detected %d implicit and %d explicit configurations for this entity!\n\n", 
                              $implicit_configurations, $explicit_configurations;

         # The reporting setup stuff will go here, later...
         @tempuncleanAList = ();
         @tempuncleanFList = ();
         push( @uncleanEList, $entity_name);
         push( @uncleanEOList, $entityNameToMDAOrdinal{$entity_name});
         for ($ord_count5 = 0; $ord_count5 < $arch_ord_counter; $ord_count5++) {  
            $arch_ordinal = $arch_ord_list[$ord_count5];
            push( @tempuncleanAList, $A_list[$arch_ordinal]);
            push( @tempuncleanFList, $ECA_file_list[$arch_ordinal]);
            $explicit_config_filename = &make_explicit_configuration_file( $AE_list[$arch_ordinal], $A_list[$arch_ordinal]) if $write_configs;
         }
         push ( @uncleanAList, join(" ", @tempuncleanAList));
         push ( @uncleanFList, join(" ", @tempuncleanFList));
      
      # Protect against missing arches
      } elsif ($implicit_configurations == 0){
         printf STDOUT "\nBUMMER! There are no architectures for this entity!\n";
         printf STDOUT "        You won't get far in a design without an architecture for your entity!\n\n";
         push( @entitiesWithMissingArchsList, $entityBogusNameToRealName{$entity_name} );
         if ($explicit_configurations == 1) {
#            push( @missingArchList,  )
         }
         $configClean = 2;
      } else {
         #
         # Clean entity, now build a merge file for it
         #
         
         # If the config's arch is missing, but we have an implicit config, use that instead
         if ( ($explicit_configurations == 1) && ($implicit_configurations == 1) && ($configArchNotFound == 1) ) {
            $configuration_match = 0;
            printf STDOUT "\nOops! Detected an explicit configuration for this entity, but not architecture for it!\n";
            printf STDOUT "       I am going to use the implicit configuration instead\n\n";
         }
         
	 # pick a name for the merge files
  	 if ( $configuration_match != 0 ) {
              $new_file_name = "." . $C_list[$config_ord_list[0]] . ".merged";
  	 } else {
              $new_file_name = ".IMPLICIT_CFG_" . $entity_name . "_" . $A_list[$arch_ord_list[0]] . ".merged";
  	 }

	 # Add the new merge file name to the filesToKillList
	 push( @filesToKillList, $new_file_name);

         # Only add this if the files aren't being removed already...
	 if ( $removeTempFiles == 0 ) {
	    push( @filesToCleanList, $new_file_name);
	 }
	 
	 # Tie the entity name to the configuration file
	 # and tie the entity name to the MERGE ordinal counter...
	 $entity_2_cfg_files{ $entity_name } = $new_file_name;
	 $entity_2_MERGE{ $entity_name } = $MERGE_counter;

	 printf "       MERGE: The value of entity_2_cfg_files{%s} is \"%s\"\n", $entity_name, 
	         $entity_2_cfg_files{ $entity_name } if $M_tells_all;

         # Get the design's files
         @master_merge_file_list = ();
         
         # Start with the entity file
         push( @master_merge_file_list, $ECA_file_list[$ent_ord] );
         $MERGE_Ent_2_EntFile{ $entity_name } = $ECA_file_list[$ent_ord];
         
         # these are the defaults, if the files are different, they will be overwritten below
         $MERGE_Ent_2_ArchFile{ $entity_name } = $ECA_file_list[$ent_ord];
         $MERGE_Ent_2_ConfigFile{ $entity_name } = $ECA_file_list[$ent_ord];

         $master_file_count = 1;

         #
         # This spot will need some brushing to handle the difference in arch/configs later...
         #
         # What if the arch and config are in the same file?
         # What if there is no config file?  Should be blank...
         # If the arch is in a different file, save that too.
         #
         # Bug here, if there is no arch for the single explicit config, the file in position 0
         # will be used by mistake...
         #
         if ( $ECA_file_list[$arch_ord_list[0]] ne $ECA_file_list[$ent_ord] ) {
            push( @master_merge_file_list, $ECA_file_list[$arch_ord_list[0]] );
            $MERGE_Ent_2_ArchFile{ $entity_name } = $ECA_file_list[$arch_ord_list[0]];
            $master_file_count++;
         }

         # If the config is in a different file, save that too.
         if (( $ECA_file_list[$config_ord_list[0]] ne $ECA_file_list[$ent_ord] ) &&
         ( $ECA_file_list[$config_ord_list[0]] ne $ECA_file_list[$arch_ord_list[0]] ) && 
         ($configuration_match != 0) ) {
            push( @master_merge_file_list, $ECA_file_list[$config_ord_list[0]] );
            $MERGE_Ent_2_ConfigFile{ $entity_name } = $ECA_file_list[$config_ord_list[0]];
            $master_file_count++;
         }
         
         if ( ($ECA_file_list[$config_ord_list[0]] eq $ECA_file_list[$arch_ord_list[0]]) && ($configuration_match != 0)) {
            $MERGE_Ent_2_ConfigFile{ $entity_name } = $ECA_file_list[$arch_ord_list[0]];
         }

         #
         # Get the kids (instances) of this archiecture
         #
         printf STDOUT "      MERGE: Looking for the kids of this architecture\n" if $M_tells_all;
         printf STDOUT "             AInst_list[%d[%d]] = \"%s\" \n", $arch_ord_list[0],
                                     0, $AInst_list[$arch_ord_list[0]] if $M_tells_all;
         @master_merge_kid_list = split(' ', $AInst_list[$arch_ord_list[0]]);
         $master_merge_kid_cell_string = $ACell_list[$arch_ord_list[0]];
         @sorted_kid_list = sort @master_merge_kid_list;
         @unique_kid_list = ();

         # Uniquify the sorted kid list
         $last_kid = "none";
         $lcv = 0;
         for( $lcv2 = 0; $lcv2 <= $#sorted_kid_list; $lcv2++ ) {
            $this_kid_name = @sorted_kid_list[$lcv2];
            if ( $last_kid ne $this_kid_name ) {
	       @unique_kid_list[$lcv] = $this_kid_name;
	       $lcv++;
            }
            $last_kid = $this_kid_name;
	 }

	 # Output the information to a file and MDA...
	 # Prep the file 
	 $new_out = ">$new_file_name";
	 open (MERGE, $new_out) || die "Can't open output file: $new_file_name\n";

         printf MERGE "Entity: %s\n", $E_list[$ent_ord];
         printf MERGE "Architecture: %s\n", $A_list[$arch_ord_list[0]];
	 if ( $configuration_match != 0 ) {
            printf MERGE "Configuration name: %s\n", $C_list[$config_ord_list[0]];
            $temp_C_name = $C_list[$config_ord_list[0]];
	 } else {
            printf MERGE "Configuration name: No explicit configuration for this design pair!\n";          
            $temp_C_name = -1;
            $MERGE_Ent_2_ConfigFile{ $entity_name } = "";
         }
         
         #Also, make an explicit configuration file, nice for simulators...
         if ( $write_configs ) {
            $explicit_config_filename = &make_explicit_configuration_file( $E_list[$ent_ord], $A_list[$arch_ord_list[0]]);
            
            # save the filename
            $MERGE_Ent_2_ConfigFile{ $entity_name } = $explicit_config_filename;
            push( @master_merge_file_list, $explicit_config_filename );
         }

         # Print the files (in analysis correct order)
         printf MERGE "Files: %s \n", join(" ", @master_merge_file_list);

         # Print the kids
         printf MERGE "Instances: %s \n", join(" ", @unique_kid_list);
         
         $arch_ord = $arch_ord_list[0];
         
# BUG here, sometimes $config_ord_list[0] doesn't exist...
         $config_ord = $config_ord_list[0];
         
         # Save the data into MD arrays...
         $MERGE_EList[$MERGE_counter] = $entity_name;
         $MERGE_ETNList[$MERGE_counter] = $E_trueName_list[$ent_ord];
         $MERGE_AList[$MERGE_counter] = $A_list[$arch_ord];
         $MERGE_CList[$MERGE_counter] = $temp_C_name;
         $MERGE_FList[$MERGE_counter] = join(" ", @master_merge_file_list);
         $MERGE_IList[$MERGE_counter] = join(" ", @unique_kid_list);
         $MERGE_CNList[$MERGE_counter] = $master_merge_kid_cell_string;
         $MERGE_ACList[$MERGE_counter] = $AComp_list[$arch_ord];
         
         # map the MERGE ordinal to the MDA ordinals
         $MERGE_ordinal_2_ent_MDAordinal{ $MERGE_counter } = $ent_ord;
         $MERGE_ordinal_2_arch_MDAordinal{ $MERGE_counter } = $arch_ord;
         
# What happens when this doesn't exist?         
         $MERGE_ordinal_2_config_MDAordinal{ $MERGE_counter } = $config_ord;
         printf STDOUT "\nEntity name %s\n", $E_trueName_list[$ent_ord] if $M_tells_all;
         printf STDOUT "   Entity Ord: %s Arch Ord: %s Config Ord: %s\n", $ent_ord, $arch_ord, $config_ord if $M_tells_all;
         
         # create the used package and library data for this unit
         $tempPackageList = $UPackage_list[$ent_ord] . " " . $UPackage_list[$arch_ord];
         $tempLibraryList = $ULibrary_list[$ent_ord] . " " . $ULibrary_list[$arch_ord];

         # protect against illogical configs... v2.23
         if ( defined($config_ord_list[0]) ) {
            $tempPackageList = $tempPackageList . " " . $UPackage_list[$config_ord];
            $tempLibraryList = $tempLibraryList . " " . $ULibrary_list[$config_ord];
         }

         printf STDOUT "   Entity package data: %s \n", $UPackage_list[$ent_ord] if $M_tells_all;
         printf STDOUT "   Arch package data: %s \n", $UPackage_list[$arch_ord] if $M_tells_all;
         printf STDOUT "   Config package data: %s \n", $UPackage_list[$config_ord] if $M_tells_all;
         $MERGE_PackageList[$MERGE_counter] = &make_uniq_list( $tempPackageList );
         $MERGE_LibraryList[$MERGE_counter] = &make_uniq_list( $tempLibraryList );

         #associate the entity to the ordinal of the MERGE database
         $MERGE_entity_2_ordinal{ $entity_name } = $MERGE_counter;
         
         printf MMDA "Merge Ordinal: %s | %s | %s | %s | %s | %s | %s |%s | %s | %s \n", $MERGE_counter, $MERGE_EList[$MERGE_counter],
         $MERGE_ETNList[$MERGE_counter], $MERGE_AList[$MERGE_counter], $MERGE_CList[$MERGE_counter],
         $MERGE_FList[$MERGE_counter], $MERGE_IList[$MERGE_counter], $MERGE_CNList[$MERGE_counter], $MERGE_PackageList[$MERGE_counter], $MERGE_LibraryList[$MERGE_counter] ;
         
         # Increment the number of MERGE files...
         $MERGE_counter++;
         
	 # finish this file up
	 close MERGE;
      }
   }
   # If the number of configurations is more than one, We must set a flag and halt processing in main
   close MMDA;
   return( $configClean );
}


sub make_explicit_configuration_file {
#############################
#
# This writes a VHDL configuraton file
#
#############################
   local ($localArchName);
   local ($localEntName);
   local ($newConfigName);
   local ($confFileName);
   local ($confFileNameOut);
   
   $localEntName = $_[0];
   $localArchName = $_[1];
   
   $newConfigName = "implicit_cfg_" . $localEntName . "_" . $localArchName;
   $confFileName =  $newConfigName . "." . $source_ext_list[0];
   $confFileNameOut = ">$confFileName";
   open (CFG, $confFileNameOut) || die "MECF: Can't open new configuration file $confFileName\n";
   printf CFG "-- Automatically generated configuration for entity %s\n", $localEntName;
   printf CFG "configuration %s of %s is \n", $newConfigName,  $localEntName;
   printf CFG "   for %s\n", $localArchName;
   printf CFG "   end for; \n";
   printf CFG "end %s;\n", $newConfigName;
   close CFG;	 

   # put this in the removal list
   push( @filesToCleanList, $confFileName);

   return( $confFileName );

}


sub parse_entity {
#############################
# All this will two things:
#   1) Find the entity name into global $entity_name
#   2) File the port, controlable by global variable $parse_ports
#   3) Read the file until the end of the entity
#
# This will have problems with entity containing begins...
#
#Enhancements for port parsing:
#1) Look for key token port
#2) find the token '(', call the port depth 1 here
#3) until the paren_depth is 1, look for the ':' token, alway saving the last token
#3.1)  if ":", 
#3.1.1) the last_token is the port name
#3.1.2) The next token is the port direction
#3.1.3) The rest of the string up to the ';' or ')' is the type
#3.1.4) Process the ports into the proper lists
#3.1.4.1) input list (entity_2_input)
#3.1.4.2) output list (entity_2_output)
#3.1.4.3) buffer list (entity_2_buffer)
#3.1.4.4) inout list (entity_2_inout)
#3.2) else if contains "(" increase the paren_depth
#3.3) else if contains ")" decrease the paren_depth
#4) continue
#############################

   local ( $entity_depth );
   local ( $localToken );

   # Get and save the next token   
   $entity_name = &get_token( 1 );
   $entity_Uname = "\U$entity_name";
   
   printf STDOUT "PE: Now parsing Entity \"%s\"\n", $entity_name if $PE_tells_all;
   
   # Set the nesting depth
   $entity_depth = 1;
   $parse_ports = 1;
   
   # Now continue chewing on the file until the end of the entity is reached
   # Along the way, look for the tokens in the entity_list.
   do {
      $lastToken = $localToken;
      $localToken = &look_for_magic_token( *entity_list );
      
      # All we care about for now is "begin", "end", and "port"
      if ( ($localToken eq "port") && ($parse_ports == 1) ) {
         # parse out the port statement
         $paren_depth = 0;
         do {
            # get the next token, but save the last one
            $lastToken = $localToken;
            $localToken = &get_token( 1 );
            printf STDOUT "   PE: Port Parsing, working on token \"%s\"\n", $localToken if $PE_tells_all;

            # deal with it
            if ($localToken eq ":" ) {
               # Found a port, get name and direction
               $portName = $lastToken;
               $portDir = &get_token( 1 );
               $portDir = "\L$portDir";
               printf STDOUT "   PE: Found a port \"%s\" with direction \"%s\"\n", $portName,$portDir  if $PE_tells_all;

               # get the type and bit range by parsing to ";" or ")" (at depth 0)

               # add this to the portName by appending with a '@' token

               # store the found port
               if ( $portDir eq "in" ) {
                  if ( !defined($entity_2_input{$entity_Uname}) ) {
                     $entity_2_input{$entity_Uname} = $portName;
                  } else {
                     $entity_2_input{$entity_Uname} = $entity_2_input{$entity_Uname} . " " . $portName;
                  }
               } elsif ( $portDir eq "out" ) {
                  if ( !defined($entity_2_output{$entity_Uname}) ) {
                     $entity_2_output{$entity_Uname} = $portName;
                  } else {
                     $entity_2_output{$entity_Uname} = $entity_2_output{$entity_Uname} . " " . $portName;
                  }
               } elsif ( $portDir eq "inout" ) {
                  if ( !defined($entity_2_inout{$entity_Uname}) ) {
                     $entity_2_inout{$entity_Uname} = $portName;
                  } else {
                     $entity_2_inout{$entity_Uname} = $entity_2_inout{$entity_Uname} . " " . $portName;
                  }
               } elsif ( $portDir eq "buffer" ) {
                  if ( !defined($entity_2_buffer{$entity_Uname}) ) {
                     $entity_2_buffer{$entity_Uname} = $portName;
                  } else {
                     $entity_2_buffer{$entity_Uname} = $entity_2_buffer{$entity_Uname} . " " . $portName;
                  }
               } else {
                  # error
                  printf STDOUT "   PE: Found a port \"%s\" with an unknown direction \"%s\"\n", $portName,$portDir  if $PE_tells_all;
               }
            } elsif ( $localToken =~ /\(/ ) {
               $paren_depth++;
               printf STDOUT "   PE: Port Parsing, paren_depth is \"%s\"\n", $paren_depth if $PE_tells_all;
            } elsif ( $localToken =~ /\)/ ) {
               # have to detect adjacent )) cases here
               while ($localToken =~ m/\)/g) {
                 $paren_depth--;  
                  printf STDOUT "   PE: Port Parsing, paren_depth is \"%s\"\n", $paren_depth if $PE_tells_all;
               }  
            } else {
               printf STDOUT "PE: Unknown localToken \"%s\"\n", $localToken if $PE_tells_all;
            }
         } until ( ($paren_depth <= 0) || (eof(IN) ==1 ));
      
      } else {
         $entity_depth = &depth_counter( $entity_depth, $localToken );
         printf STDOUT "PE: Entity depth is: %d, The found token is %s\n", $entity_depth, $localToken if $PE_tells_all;
      }
   }
   until ( (($entity_depth <= 1) && ($localToken eq "end")) || (eof(IN) ==1 ));

   printf STDOUT "PE: Done Parsing entity \n" if $PE_tells_all;
   if ($PE_tells_all == 1) {   
      printf STDOUT "Port report for entity %s:\n", $entity_name;   
      printf STDOUT "=======================================\n";   
      printf STDOUT "   Input ports:\n";   
      printf STDOUT "   ------------\n";
      @portList = split(" ", $entity_2_input{$entity_Uname} );
      foreach $port (@portList) {
	 printf STDOUT "      %s\n", $port;
      }

      printf STDOUT "   Output ports:\n";   
      printf STDOUT "   -------------\n";
      @portList = split(" ", $entity_2_output{$entity_Uname} );
      foreach $port (@portList) {
	 printf STDOUT "      %s\n", $port;
      }

      printf STDOUT "   Buffer ports:\n";   
      printf STDOUT "   -------------\n";
      @portList = split(" ", $entity_2_buffer{$entity_Uname} );
      foreach $port (@portList) {
	 printf STDOUT "      %s\n", $port;
      }

      printf STDOUT "   Inout ports:\n";   
      printf STDOUT "   ------------\n";
      @portList = split(" ", $entity_2_inout{$entity_Uname} );
      foreach $port (@portList) {
	 printf STDOUT "      %s\n", $port;
      }
   }
   return;
}


sub parse_package {
#############################
# This will a few things:
#   1) Find the package name into global $package_name
#   2) Read the file until the end of the package
#   3) Parse out all the declared components 
#
#  This will return a value in either package_body_name or package_name
#
#  This will ignore sub packages dependencies, I think
#     Will make_order_package catch these?
#############################

   local ( $package_depth );
   local ( $localToken );

   # Get and save the next token   
   $localToken = &get_token( 1 );
   
   if ( $localToken =~ /body/i ) {
      $package_body_name = &get_token( 1 );
      $package_name = "";
   } else {
      $package_body_name = "";
      $package_name = $localToken;
   }
   
   printf STDOUT "PE: Now parsing Package \"%s\"\n", $package_name if $PP_tells_all;
   
   # Set the nesting depth with an implicit begin...
   $package_depth = 1;
   
   # Now continue chewing on the file until the end of the package is reached
   # Along the way, look for the tokens in the parse_package_list.
   do {
      $lastToken = $localToken;
      $localToken = &look_for_magic_token( *parse_package_list );
      
      #
      # Hunt components declarations
      if ( $localToken eq "component" ) {
         printf STDOUT "PP: The line is \"%s\"\n", $saved_line if $PP_tells_all;
         # Get the name of the component
         if ( !($lastToken =~ /\bend\b/i) ) {
            $package_component_list[$package_component_count] = &get_token( 1 );
            printf STDOUT "PP: Got package component name \"%s\" \n", $package_component_list[$package_component_count] if $PP_tells_all;
            $package_component_count++;
         } 
      }

      # All we care about for now is "begin" and "end"
      $package_depth = &depth_counter( $package_depth, $localToken );
      printf STDOUT "PP: Package depth is: %d, The found token is %s\n", $package_depth, $localToken if $PP_tells_all;
      }
   # changed the depth counting to trip only when less than 1, not <= anymore...
   until ( (($package_depth < 1) && ($localToken eq "end")) || (eof(IN) == 1 ));

   printf STDOUT "PP: Done Parsing package \n" if $PP_tells_all;   
   return;
}

sub parse_configuration {
#############################
# All this will do is completely parse to the end of any configuration
# Only simple configurations are handled for now, that is to say
# I will only get the first "for" and ignore the rest...
#
# The things that are parsed out are
#    Configuration name                    $configuration_name
#    Entity name for the configuration     $configuration_ent_name
#    The arch name for this entity         $configuration_arch_name
#############################

   local ( $localToken );
   local ( $configDepth );

   $configDepth = 1;
   # First, save the configuration's name, and it's entity name
   $configuration_name = &get_token( 1 );
   $configuration_ent_name = &get_token( 2 );

   printf STDOUT "Now parsing Configuration \"%s\" of Entity \"%s\"\n", $configuration_name, $configuration_ent_name if $PC_tells_all;
   
   # Now look for its architecture name after the first "for"
   $configuration_arch_name = "";

   # Now continue reading the file until the end of the configuration is reached
   # Look for the architecture after the first "for"
   do {
      $lastToken = $localToken;

      #Look for the first "for" keyword, the next token is the arch name for this config
      $localToken = &look_for_magic_token( *config_keywords );
         
      if ( ($configuration_arch_name eq "") && ( $localToken eq "for" )) {
           $configuration_arch_name = &get_token( 1 );
           printf STDOUT "Found architecture \"%s\" of entity \"%s\", for configuration \"%s\"\n", $configuration_arch_name, $configuration_ent_name, $configuration_name
           if $PC_tells_all;
      }
      elsif ( ($localToken eq "begin") || ($localToken eq "end") ) {
         $configDepth = &depth_counter( $configDepth, $localToken );     
      }
      printf STDOUT "PC: localToken is \"%s\" and configDepth is \"%s\" \n", $localToken, $configDepth if $PC_tells_all;
   }
   until ((($localToken eq "end") && ($configDepth <= 0 )) || (eof(IN) ==1 ) ) ;
   printf STDOUT "PC: Parse Configuration done\n" if $PC_tells_all;
}

sub depth_counter {
##########################
# 
# This determines if and how the nesting depth should be counted
#
# It returns the new depth
#
##########################
   local ( $DCToken );
   local ( $nested_depth );
   local ( $next_token );
   local ( $magic_word );
   
   $nested_depth = $_[0];
   $DCToken = $_[1];

   printf STDOUT "DC: The $DCToken is \"%s\"\n", $DCToken if $DC_tells_all;
   printf STDOUT "DC: The input depth is \"%s\"\n", $nested_depth if $DC_tells_all;
         
   # increase the depth if begin, decrease if end
   if ( $DCToken eq "begin" ) {
      $nested_depth++;
   } 
   elsif ( $DCToken eq "end" ) {
      #DON'T COUNT units, record, for, case, component, if, generate, loop 
      # Should really "push" this token back into the list...
      $next_token = &get_token(1);

      printf STDOUT "DC: The next_token is %s\n", $next_token if $DC_tells_all;

      $extra_end_found = 0;
         
      #see if this is a bogus extra end statement associated with the tokens in the list
      foreach $magic_word ( @not_quite_end_list ) {
         printf STDOUT "   DC: Comparing for next token \"%s\" with \"%s\"\n", $next_token, $magic_word if $DC_tells_all;
         if ( $next_token =~ /\b$magic_word\b/i ) {
             printf STDOUT "   DC: This token \"%s\" is extra because it is followed by \"%s\"\n", 
                           $DCToken, $next_token if $DC_tells_all;
            $extra_end_found = 1;
            last;
         }
      }
      if ( $extra_end_found == 0) {
         $nested_depth--;
#  8/15/96
# What the hell was this supposed to do? 10/23/96
#          $saved_line
      }
      
      # push the token back into the line
      $saved_line = join (' ', $next_token, $saved_line);
   }
    printf STDOUT "DC: The local nested depth is %d\n", $nested_depth if $DC_tells_all;
    return( $nested_depth );
}

sub setup_VHDL_parse {
   #############################
   #
   # This inits all the temp variables and lists for VHDL parsing
   #
   #############################

    $found_config_token = 0;
    $config_list_count = 0;
    @configuration_list = ();
    $component_count = 0;
    $package_component_count = 0;
    @instance_list = ();
    @cell_list = ();
    $instance_count = 0;
    @component_list = ();
    @package_component_list = ();
    @use_list = ();
    $package_count = 0;
    $package_name = "";
    $package_body_name = "";
    $entity_name = "";
    $arch_name = "";
    $arch_ent_name = "";
    $configuration_name = "";
    $configuration_ent_name = "";
    $configuration_arch_name = "";
    $package = "";
    $component = "";
    $depth_counter = 0;
    $found_arch_token = 0;
    $in_arch = 0;

}

sub save_parse_info {
   #############################
   #
   # First argv is the design unit type (E|A|C|P|PB)
   # 
   # This just gathers all the info into the multi-D arrays and writes it to a file.
   #
   #############################
   #
   # The new (v1.2) parse data structure should look like
   # type                 : (ent|arch|config|package)
   #                      : 
   # entName              : was E_list and should be upper case
   #                      : Scalar name of the parsed entity
   #                      : init'ed in set_up_HS_data_struc, used in merge
   # entRealName          : was E_trueName_list
   #                      : Scalar real name of the parsed entity
   #                      : used in merge
   # archName             : was A_list, upper case
   #                      : Scalar name of the parsed architecture
   #                      : init'ed in set_up_HS_data_struc, used in merge
   # archEntName          : was AE_list, upper case
   #                      : Scalar name of the entity tied to the arch
   #                      : init'ed in set_up_HS_data_struc, used in merge
   # configName           : was C_list, upper case
   #                      : Scalar name of the parsed configuration
   #                      : init'ed in set_up_HS_data_struc, used in merge
   # configEntName        : was CE_list, upper case
   #                      : Scalar name of the entity for the configuration
   #                      : init'ed in set_up_HS_data_struc, used in merge
   # configArchName       : was CA_list, upper case
   #                      : Scalar name of the architecture for the configuration
   #                      : needed in merge
   # archComponentList    : was AComp_list,
   #                      : List of components declared in the arch
   #                      : needed in merge
   # archInstanceList     : was AInst_list
   #                      : List of instances in the arch
   #                      : needed in merge
   # archCellList         : was ACell_list
   #                      : List of Cellname:instances in the arch
   #                      : needed in reporting
   # archConfigList       : was AConfig_list
   #                      : List of configes in the Arch
   #                      : needed in merge
   # packName             : was P_list
   #                      : Scalar name of the parsed package
   #                      : needed in merge_packages
   # packBodyName         : was PB_list
   #                      : Scalar name of the parsed package body
   #                      : needed in merge_packages
   # packComponentList    : was PComponent_list
   #                      : List of component found in package
   #                      : needed in merge_packages
   # unitPackages         : was UPackage_list
   #                      : unique list of package name for the design unit (E|A|C|P)
   #                      : needed in merge, merge_packages, and SMFN_PrintPackagePrereqs 
   # unitCompletePackages : was UCompletePackage_list
   #                      : uniqued list of libname.packname for design unit (E|A|C|P)
   #                      : Not yet used
   # unitLibraries        : was ULibrary_list
   #                      : uniqued list of library names for design unit (E|A|C|P)
   #                      : needed in merge
   # fileName             : was ECA_file_list
   #                      : Scalar file name, duh!
   #                      : needed in unclean_help, merge, merge_packages
   # fileDate             : New variable, could use 'stat' to find the needed info
   #                      : Scalar file date, not yet used...
   #############################

   #    &print_info;
   
   # Get the type
   local( $type ) = $_[0];
 
   # save everything for the file parse into the "multi-D arrays"     
   # Also, in v1.2, save into the new data structure.   
    $ECA_file_list[$ordinal_counter]         = $in;
    $E_list[$ordinal_counter]                = "\U$entity_name";
    $E_trueName_list[$ordinal_counter]       = "$entity_name";
    $A_list[$ordinal_counter]                = "\U$arch_name";
    $AE_list[$ordinal_counter]               = "\U$arch_ent_name";
    $C_list[$ordinal_counter]                = "\U$configuration_name";
    $CE_list[$ordinal_counter]               = "\U$configuration_ent_name";
    $CA_list[$ordinal_counter]               = "\U$configuration_arch_name";
    $AComp_list[$ordinal_counter]            = join(' ', @component_list);
    $AInst_list[$ordinal_counter]            = join(' ', @instance_list);
    $ACell_list[$ordinal_counter]            = join(' ', @cell_list);
    $AConfig_list[$ordinal_counter]          = "";
    $P_list[$ordinal_counter]                = $package_name;
    $PB_list[$ordinal_counter]               = $package_body_name;
    $PComponent_list[$ordinal_counter]       = join(' ', @package_component_list);
    $UPackage_list[$ordinal_counter]         = join(' ', @unitPackageList);
    $UCompletePackage_list[$ordinal_counter] = join(' ', @unitCompletePackageList);
    $ULibrary_list[$ordinal_counter]         = join(' ', @unitLibraryList);

    # Save the array to disk file
    printf MDA "Ordinal %d: %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s \n", 
    $ordinal_counter, 
    $E_trueName_list[$ordinal_counter], $E_list[$ordinal_counter], $A_list[$ordinal_counter],
    $AE_list[$ordinal_counter], $C_list[$ordinal_counter], $CE_list[$ordinal_counter],
    $CA_list[$ordinal_counter], $AComp_list[$ordinal_counter], $AInst_list[$ordinal_counter], $ACell_list[$ordinal_counter],
    $P_list[$ordinal_counter], $PB_list[$ordinal_counter], $PComponent_list[$ordinal_counter],
    $UPackage_list[$ordinal_counter], $ULibrary_list[$ordinal_counter], $UCompletePackage_list[$ordinal_counter],
    $ECA_file_list[$ordinal_counter];
        
    $ordinal_counter++;

    # these must be cleared after each save because we need fresh lists
    # for each Ent|arch|config|package, so we want a empty list for the next save.
    @unitPackageList = ();
    @unitCompletePackageList = ();
    @unitLibraryList = ();

    # Save the record to the disk
    #       1) PVHDLDS  : for the parsed data
    #       2) MVHDLDS  : for the merged data
    #       3) MPVHDLDS : for the merged package data

}

sub print_info {

    $out      = ">.HS_parse_file";
    open (OUT, $out) || die "Can't open parse output file: $new\n";   

      printf OUT "File name: %s\n", $in;
      if ( $entity_name ne "" ) {
         printf OUT "Entity name: %s\n", $entity_name;
      }
      if ( $arch_name ne "" ) {
         printf OUT "Architecture name: %s\n", $arch_name;
      }
      if ( $arch_ent_name ne "" ) {
         printf OUT "Architecture's Entity name: %s\n", $arch_ent_name;
      }
      if ( $configuration_name ne "" ) {
         printf OUT "Configuration name: %s \n", $configuration_name;
      }
      if ( $configuration_ent_name ne "" ) {
         printf OUT "Configuration's Entity name: %s \n", $configuration_ent_name;
      }
      if ( $configuration_arch_name ne "" ) {
         printf OUT "Configuration's Architecture name: %s \n", $configuration_arch_name;
      }
      if ( $package_name ne "" ) {
         printf OUT "Package name: %s \n", $package_name;
      }
      foreach $package ( @unitCompletePackageList ) {
         printf OUT "Used package name: %s\n", $package;
      }      
      foreach $component ( @component_list ) {
         printf OUT "Component: %s\n", $component;
      }
      foreach $component ( @instance_list ) {
         printf OUT "Instance %s\n", "\U$component";
      }
      foreach $component ( @cell_list ) {
         printf OUT "Cell %s\n", "\U$component";
      }
    close OUT;

}

sub parse_architecture {
#############################
# All this will do is completely parse to the end of any architecture
# The things that are parsed out are
#    architecture name                    $arch_name
#    Entity name for the architecture     $arch_ent_name
#    and declared components in the arch dec part
#    any instanted components in the arch statement part
#
#  Will parse the arch declarative section for components and ignore everything else
#
#  There are only concurrent statements inside the statement part of the arch
#  The valid concurrent statements are:
#    -block                         : HANDLED - parsed around but the declarations are parsed!!
#    -process                       : HANDLED - parsed around
#    -concurrent procedure call     : HANDLED - Detected by no port map...
#    -concurrent asssertion         : HANDLED - with label exclusion
#    -concurrent signal assignment  : HANDLED - with label exclusion
#    -component instantiation       : HANDLED - that is the whole point!
#    -generate                      : HANDLED - with label exclusion
#
#############################
   local ( $archDepth );
   local ( $got_to_first_begin );
   local ( $target_instance );
   local ( $keep_hunting );
   local ( $valid_instance );
   local ( $tempToken1 );
   local ( $tempToken2 );
   local ( $inProcess );
   local ( $inBlock );
   local ( $inComponent );
   local ( $inSubroutine );
   local ( $tempLabel );
   local ( $nextToken );
   local ( $parsingASP );
   local ( $temp_real_counter );
   local ( $temp_real_string1 );
   local ( $temp_real_string2 );

   $keep_hunting = 1;
   $inProcess = 0;
   $inBlock = 0;
   $inComponent = 0;
   $inSubroutine = 0;

   # get the architecture and the entity that it is bound to
   $arch_name = &get_token( 1 );
   $arch_ent_name = &get_token( 2 );

   printf "      Architecture \"%s\" of entity \"%s\" found\n", $arch_name, $arch_ent_name if $verbose_mode;

   printf STDOUT "\nNow parsing architecture \"%s\" of Entity \"%s\"\n", $arch_name, $arch_ent_name if $PA_tells_all;

   $archDepth = 0;
   $got_to_first_begin = 0;
   
   $parsingStatementPart = 0;

   # eat the "is"
   $lastToken = &get_token( 1 );

   # Now continue reading the file until the end of the architecture is reached
   # and extract the following items:
   # a) component declarations
   # b) cell instances
   
   do {
      printf STDOUT "   PA: Parsing arch \"%s\", line: \"%s\"\n", $arch_name, $saved_line if $PA_tells_all;
      
      if ( $parsingStatementPart == 0 ) {
         # shift the localToken...
         $lastToken = $localToken;
      
         # get the next token
         $localToken = &look_for_magic_token( *ADPKeywords );
         printf STDOUT "      PA: In ADP, lastToken is \"%s\", the current token is \"%s\"\n", $lastToken, $localToken  if $PA_tells_all;
      
         #
         # Hunt components declarations
         if ( $localToken eq "component" ) {
            printf STDOUT "      PA: In ADP, Hunting components in parse_arch, the line is \"%s\"\n", $saved_line if $PA_tells_all;
            # Get the name of the component
            # don't treat the component as a virtual begin, depth_counter doesn't recognize its end
            if ( !($lastToken =~ /\bend\b/i) ) {
               $inComponent = 1;
               $component_list[$component_count] = &get_token( 1 );
               printf STDOUT "      PA: In ADP, Got component name \"%s\" \n", $component_list[$component_count] if $PA_tells_all;
               $component_count++;

               # could speed things up here by shortening the list for look_for_magic_token to end
            } 
         }
         
         #
         # Hunt subroutines
         elsif ( ($localToken eq "procedure") || ($localToken eq "function") ) {
            printf STDOUT "      PA: In ADP, Hunting subs in parse_arch, the line is \"%s\"\n", $saved_line if $PA_tells_all;
            $inSubroutine = 1;
            # could speed things up here by shortening the list for look_for_magic_token to begin and end
         }
         #
         # Hunt depth
         elsif ( ($localToken eq "begin") || ($localToken eq "end") ) {
            $archDepth = &depth_counter( $archDepth, $localToken );
            printf STDOUT "      PA: In ADP, depth is \"%d\", the token is \"%s\"\n", $archDepth, $localToken if $PA_tells_all;

            # adjust the flags and try to handle block comps and subs
            if ( (($inBlock != 0) || ($archDepth == 0)) && ($localToken eq "end") ) {
               if ( $inComponent == 1)  {
                  $inComponent = 0;
                  # restore list here
               }
            
               if ( $inSubroutine == 1 ) {
                  $inSubroutine = 0;
                  # restore list here
               }
            }
            
            # Handle a normal exit to the ASP section, aka "the first begin token"
            if ( ($archDepth == 1) && ($inSubroutine == 0 ) 
                 && ($inComponent == 0 ) && ($localToken eq "begin") ) {
               printf STDOUT "      PA: In ADP, Done parsing the Arch declarative part \n" if $PA_tells_all;
               $parsingStatementPart = 1;
            }
            
            # handle the block declarative part exit here...
            # this could be a little messed up...
            if ( ($archDepth != 0) && ($localToken eq "begin") && ($inBlock != 0) ) {
               printf STDOUT "PA: Done parsing the block declarative part \n" if $PA_tells_all;
               # bounce back to the statement parsing section 
               $parsingStatementPart = 1;
            }
         }

      } else {
         if ($inProcess) {
            printf STDOUT "      PA: ASP is currently in a PROCESS statement\n"  if $PA_tells_all;
         } elsif ($inBlock) {
            printf STDOUT "      PA: ASP is currently in a BLOCK statement\n"  if $PA_tells_all;
         }
         # shift the localToken...
         $lastToken = $localToken;
      
         # get the next token
         $localToken = &look_for_magic_token( *ASPKeywords );
         printf STDOUT "      PA: In ASP, lastToken is \"%s\", the current token is \"%s\"\n", $lastToken, $localToken  if $PA_tells_all;

         #
         # Hunt processes, and parse thru until the "end" someday but for now, cheat by just setting a switch...
         if ( $localToken eq "process" ) {
            if ($lastToken eq "end") {
               $inProcess = 0;
               printf STDOUT "      PA: --------Out of process statement now\n" if $PA_tells_all;
            } else {
               $inProcess = 1;
               printf STDOUT "      PA: ++++++++In a process statement now\n" if $PA_tells_all;
            }
         }
      
         #
         # Hunt blocks, and parse thru until the block "begin" statement
         elsif ( $localToken eq "block" ) {
            if ($lastToken eq "end") {
               $inBlock--;
               printf STDOUT "      PA: --------Out of block statement now, block level %d \n", $inBlock  if $PA_tells_all;
            } else {
               $inBlock++;
               printf STDOUT "      PA: ++++++++In block statement now, block level %d \n", $inBlock  if $PA_tells_all;
               
               # Now, we gots to parse out the block declarative part
               $parsingStatementPart = 0;
               printf STDOUT "      PA: Start parsing the BLOCK declarative part \n" if $PA_tells_all;
            }
         }

         #
         # Hunt instances
         elsif (( $localToken eq ":" )  && ($inProcess == 0) ) {
            
            # This is the part that finds instances.
            # It should be changed to a direct detect instead of a negative logic proof

            printf STDOUT "      PA: in ASP, Hunting instances in parse_arch, the line is \"%s\"\n", $saved_line if $PA_tells_all;
            # Get the name of the instance
            if ( !($lastToken =~ /\bend\b/i) ) {
               #
               # Check for the following type of arrangement
               # LIBRARY.PACKAGE.COMPONENT
               #
               $target_cellName = $lastToken;
               $target_instance = &get_token( 1 );
               $nextToken = &get_token( 1 );
               $upperNextToken = "\U$nextToken";
               $valid_instance = 0;
            
               if ( $nextToken eq "." ) {
                  # Make sure that the target_instance token is in the library_list a_array
                  # Then get the new target token
                  #if ( $local_library_list{ $target_instance } != 0 ) {
                     $target_instance = &get_token( 3 );
                     &parse_to_end_of_statement;
                 # }
               } elsif ( $upperNextToken eq "PROCESS" ){
                  $inProcess = 1;
                  printf STDOUT "      PA: ++++++++In a process statement now\n" if $PA_tells_all;
               } elsif ( $upperNextToken eq "BLOCK" ){
                  $inBlock++;
                  printf STDOUT "      PA: ++++++++In block statement now, block level %d \n", $inBlock  if $PA_tells_all;
               } elsif ( $nextToken eq "<=" ){
                  # found a labeled continous assignment, proceed.
                  printf STDOUT "      PA: In HI, Detected a labeled continous assignment, the nextToken is \"%s\"\n", $nextToken if $PA_tells_all;
                  $valid_instance = 2;
               } else {
                  # push it back on the saved_line and the real_saved_line
                  $saved_line = join(" ", $nextToken, $saved_line);
                  $real_saved_line = join(" ", $nextToken, $real_saved_line);

        	  # look for exclusions, this will handle asserts and generate statements also
        	  $token_real_string2 = &get_stringToken( 1 );
        	  $token_real_string2 = "\L$token_real_string2";
        	  
# BUG HERE        # This is never set!!
        	  $token_real_string1 = "\L$token_real_string1";

        	  if ( ($token_real_string2 eq "generic") || ($token_real_string2 eq "port") ) {
                     # found a valid instance, parse out the rest of the line
                     printf STDOUT "      PA: In HI, detected instance name \"%s\" from \"%s\"\n", $target_instance,  $token_real_string2  if $PA_tells_all;
                     $valid_instance = 1;
        	  } 
        	  # looking for continous procedure here, there won't be port or generic
        	  elsif ( ($token_real_string2 =~ /\(/) || ($token_real_string2 =~ /\<\=/) )  {
                     $valid_instance = 0;
                     printf STDOUT "      PA: In HI,  Rejecting token \"%s\" due to \"%s\" \n", $target_instance, $token_real_string2 if $PA_tells_all;
        	  } 
        	  # looking for a ";" in the instance or next token, this is not likely...
        	  elsif ( ($token_real_string2 =~ /\;/ ) || ($token_real_string1 =~ /\;/) )  {
                     $valid_instance = 0;
                     printf STDOUT "      PA: In HI,  Rejecting token \"%s\" due to \"\;\" \n", $target_instance if $PA_tells_all;
        	  }
               }
               # if instance, keep it
               # WHAT THE HELL IS THE DIFFERENCE BETWEEN A CELL AND AN INSTANCE HERE???
               if ( ($valid_instance == 1) ) {
                  # must put in the cell name save here also
                  if ($libraryCellArray{"\U$target_instance"} != 1) {
                     $instance_list[$instance_count] = "\U$target_instance";
                     # added in v2.24 to get the real names of missing entities
                     $instanceName2instanceTrueName{$instance_list[$instance_count]} = $target_instance;
                     $cell_list[$instance_count] = "\U$target_instance" . ":" . "$target_cellName";
                     printf STDOUT "      PA: In HI,  Got instance name \"%s\" \n", $instance_list[$instance_count] if $PA_tells_all;
                     printf STDOUT "      PA: In HI,  The Instance:Cell name is \"%s\" \n", $cell_list[$instance_count] if $PA_tells_all;
                     $instance_count++;
                     printf STDOUT "         Found instance name \"%s\" (cell name \"%s\")\n", $target_instance, $target_cellName, if $verbose_mode;
                  } else {
                     printf STDOUT "      PA: In HI,  The Instance:Cell name is \"%s\":\"%s\" \n", $target_instance, $target_cellName if $PA_tells_all;
                     printf STDOUT "         Found library cell instance \"%s\" (cell name \"%s\")\n", $target_instance, $target_cellName, if $verbose_mode;
                }
               } elsif ( $valid_instance == 2) {
                  printf STDOUT "      PA: In HI,  Found labeled continous assignment, Ignoring token %s\n", $target_instance if $PA_tells_all;
               } else {
                  printf STDOUT "      PA: In HI,  Rejected token \"%s\" \n", $target_instance if $PA_tells_all;
               }
            } 
         }
         #
         # Hunt depth
         elsif ( ($localToken eq "begin") || ($localToken eq "end") ) {
            $archDepth = &depth_counter( $archDepth, $localToken );
         }
      
      }
   }
   until ( ( ($localToken eq "end") && ($archDepth <= 0 ) && ($parsingStatementPart == 1) ) || (eof(IN) == 1) ) ;
   printf STDOUT "PA: returning now..." if $PA_tells_all;
}

sub parse_to_end_of_statement {
# parse until a ";" is found

   local ( $local_token );
   local ( $return_string );
   
   $local_token = &get_token( 1 );
   $return_string = $local_token;
   #printf STDOUT "PTEOS: Starting to trash tokens \n" ;
   while ( ($local_token !~ /\;/) && (eof(IN) != 1)  ) {
      #printf STDOUT "   \"%s\" \n", $local_token ;
      $local_token = &get_token( 1 );
      $return_string = $return_string . " " . $local_token;
   }
   #printf STDOUT "PTEOS: Ending trashing \n" ;
   
   return $return_string;
}

sub get_rest_of_Verilog_statement {
# parse until a ";" is found

   local ( $local_token );
   local ( $return_string );
   
   #$GROVS_tells_all = 0;
   printf STDOUT "\nGROVS: In the GROVS!! \n", if $GROVS_tells_all;
   $local_token = &get_Verilog_token( 1 );
   $return_string = $local_token;
   #printf STDOUT "GROVS: Starting to read \n" ;
   while ( ($local_token !~ /\;/) && (eof(IN) != 1) ) {
      printf STDOUT "   \"%s\" \n", $local_token, if $GROVS_tells_all ;
      #$GVT_tells_all = 1;
      $local_token = &get_Verilog_token( 1 );
      #$GVT_tells_all = 0;
      $return_string = $return_string . " " . $local_token;
   }
   
   if (eof(IN) == 1)  {
      printf STDOUT "GROVS: End of File detected!! \n", if $PTEOVS_tells_all;
   }
   printf STDOUT "GROVS: Ending read, returning \"%s\" \n\n", $return_string, if $GROVS_tells_all ;
   return $return_string;
}

sub parse_to_end_of_Verilog_statement {
# parse until a ";" is found

   local ( $local_token );
   local ( $return_string );
   
   $calledBy = $_[0];
   
   printf STDOUT "\nPTEOVS: In the PTEOVS, called by \"%s\"!! \n", $calledBy if $PTEOVS_tells_all;
   $local_token = &get_Verilog_token( 1 );
   #printf STDOUT "PTEOVS: Trashing tokens: \n";
   while ( ($local_token !~ /\;/) && (eof(IN) != 1) ) {
      printf STDOUT "    \"%s\"\n", $local_token, if $PTEOVS_tells_all;
      $local_token = &get_Verilog_token( 1 );
   }
   if (eof(IN) == 1)  {
      printf STDOUT "PTEOVS: End of File detected!! \n", if $PTEOVS_tells_all;
   }
   printf STDOUT "PTEOVS: Done trashing, returning \"%s\" \n\n", $local_token, if $PTEOVS_tells_all;
   
   return $local_token;
}

sub look_for_magic_token {
##########################
#
# An all important subroutine!
# This looks thru the list given by the magic_word_list and
# returns the found token from that list
#
# It also reforms the saved_line so that later parsing start
# from the right spot...  Think about it...
#
# The Following GLOBAL VARIABLES ARE USED and changed
#
#   split_line : list
#   saved_line : String
#
#  saved_line must be set!
#   
##########################
   local ( $localToken );
   local ( $foundMagicToken );
   local ( $tempToken1 );
   local ( $tempToken2 );
   local ( @temp_split_line );
   local ( $magic_word );
   local ( *magic_token_list ) = @_;

   # Prep the search
   $foundMagicToken = 0;
   
# 8/13/96 v1.0b3 fix to split the first line properly...
   @temp_split_line = split(/\b/, $saved_line);
   $saved_line = join(' ', @temp_split_line); 

   @split_line = split(' ', $saved_line);
   
   $localToken = $lastToken;
   while ( ($foundMagicToken == 0) && (eof(IN) != 1) ) {   
      printf STDOUT "GMT: Magic token hunt now looking at line: \"%s\"\n", $saved_line if $GMT_tells_all ;
      foreach $magic_word ( @magic_token_list ) {
         printf "   GMT: Looking for token: \"%s\"\n",$magic_word if $GMT_tells_all;
         if ( $saved_line =~ /\b$magic_word\b|\B$magic_word\B/i ) {
            printf "   GMT: Line contains token \"%s\" \n", $magic_word if $GMT_tells_all;
            while ( @split_line ) { 
               printf STDOUT "      GMT: Scanning line \"%s\"\n", join(' ', @split_line) if $GMT_tells_all;
               $lastToken = $localToken;
               $localToken = shift( @split_line );
               printf STDOUT "      GMT: Last token is \"%s\", new token is \"%s\"\n", $lastToken, $localToken if $GMT_tells_all;
               if ( $localToken =~ /^--/ ){
                  $localToken = "";
                  last;
               }
               # look at every token but do an EXACT match!
               foreach $local_magic_word ( @magic_token_list ) {
                  $tempToken1 = "\U$local_magic_word";
                  $tempToken2 = "\U$localToken";
                  printf STDOUT "      GMT: Now comparing \"%s\" to \"%s\"\n", $tempToken1, $tempToken2 if $GMT_tells_all;
                  if ( $tempToken1 eq $tempToken2 ) {
                     $localToken = $local_magic_word;
                     $foundMagicToken = 1;
                     printf "          GMT: Found token \"%s\" \n", $local_magic_word if $GMT_tells_all;
                     last;
                  }
               }
               # If one was found, all done!
               if ( $foundMagicToken == 1 ) {
                  last;
               }
            }
            # This is to bump us out of the foreach loop
            last;
         }
      }
      
      # If no token found, get the next line
      if ( ($foundMagicToken == 0) && (eof(IN) != 1) ) {
         $saved_line = <IN>;
         $real_saved_line = $saved_line;
         chop $saved_line;
         @temp_split_line = split(/\b/, $saved_line);
         $saved_line = join(' ', @temp_split_line); 
         @split_line = split(' ', $saved_line);
      } elsif ( eof(IN) == 1 ) {
         printf "END OF FILE FOUND!!!\n" if $GMT_tells_all;
         last;
      }
   }
   
   # Now reconsititute the split line into saved line so we can parse it later.
   $saved_line = join(' ', @split_line); 
    printf "GMT: Returning token \"%s\" \n", $localToken if $GMT_tells_all;

   return ( $localToken );
}

sub get_token {
#################
#
# saved_line must be set! 
# 
# modified 9/13/97 to fix '(' and ')' issues
# modified 6/15/98 to fix '[' and ']' issues
# modified 6/15/98 to fix '*' regexp issue
# modified 6/15/98 to fix '?' regexp issue
# modified 6/15/98 to fix '+' regexp issue
#################
   local ( $number_of_tokens );
   local ( $get_next_line );
   local ( $localToken );
   local ( $newToken );
   local ( $offset );
   
   $offset = $_[0];
   
   $number_of_tokens = 0;
   @split_line = split(' ', $saved_line);   
   printf STDOUT "GT: Starting with line \" %s \" \n", $real_saved_line if $GT_tells_all;

   while ( ($number_of_tokens < $offset) && (eof(IN) != 1) ) {
      $get_next_line = 0;
      $localToken = shift( @split_line );
            
      # chop the token out of the string
      printf STDOUT "   GT: Removing token \"%s\" from line \" %s \" \n", $localToken, $real_saved_line if $GT_tells_all;
      
      $newToken = $localToken;
      
      # If the token contains illegal chars, protect it for the regexp with '\'
      $newToken =~ s/\(/\\\(/g;
      $newToken =~ s/\)/\\\)/g;
      $newToken =~ s/\?/\\\?/g;
      $newToken =~ s/\+/\\\+/g;
      $newToken =~ s/\*/\\\*/g;
      $newToken =~ s/\[/\\\[/g;
      $newToken =~ s/\]/\\\]/g;
      printf STDOUT "   GT: Fixed %s to %s \n", $localToken, $newToken if $GT_tells_all;
      
      # Split based on the token and get everything after the token.
      $real_saved_line =~ /${newToken}/;
      $real_saved_line = $';
      @real_split_line = split(' ', $real_saved_line);
      
      #do {
      #   $realLocalToken = shift( @real_split_line );
      #} until ($realLocalToken eq $localToken);
      #$real_saved_line = join(" ", @real_split_line);
      
      printf STDOUT "   GT: Real line is now \" %s \" \n", $real_saved_line if $GT_tells_all;
      
      # Comment line, blow off the rest
      if ( $localToken =~ /^--/ ) {
          $get_next_line = 1;
      } 
      # Real token, count it
      elsif ( $localToken ne "" ) {
         $number_of_tokens++;
      } else {
         $get_next_line = 1;               
      }
      # Get and prep the next line to read
      if ( ($get_next_line == 1 ) && (eof(IN) != 1)) {
         $saved_line = <IN>;
         chop $saved_line;
         $real_saved_line = $saved_line;
         @temp_split_line = split(/\b/, $saved_line);
         $saved_line = join(' ', @temp_split_line); 
         @split_line = split(' ', $saved_line);
         @real_split_line = split(' ', $real_saved_line);
      } elsif ( eof(IN) == 1 ) {
         printf "END OF FILE FOUND!!!\n" if $GT_tells_all;
         last;
      }
   }

   printf STDOUT "GT: Snabbed token \"%s\" \n", $localToken if $GT_tells_all;
   $saved_line = join(' ', @split_line);
   $real_saved_line = join(' ', @real_split_line);
   printf STDOUT "GT: --Setting real_saved_line to \"%s\" \n", $real_saved_line if $GT_tells_all;
   printf STDOUT "GT: --Setting saved_line to \"%s\" \n\n", $saved_line if $GT_tells_all;

   return ( $localToken );
}

sub get_stringToken {
#################
#
# saved_line must be set! 
# 
#################
   local ( $number_of_tokens );
   local ( $get_next_line );
   local ( $localToken );
   local ( $offset );
   
   $offset = $_[0];
   
   $number_of_tokens = 0;
   @real_split_line = split(' ', $real_saved_line);   
   printf STDOUT "GST: Starting with line \" %s \" \n", $real_saved_line if $GST_tells_all;
   
   while ( ($number_of_tokens < $offset) && (eof(IN) != 1) ) {
      printf STDOUT "   GST: Working on line \" %s \" \n", $real_saved_line if $GST_tells_all;
      $get_next_line = 0;
      $localToken = shift( @real_split_line );
      
      # Comment line, blow off the rest
      if ( $localToken =~ /^--/ ) {
          $get_next_line = 1;
      } 
      # Real token, count it
      elsif ( $localToken ne "" ) {
         $number_of_tokens++;
      } else {
         $get_next_line = 1;               
      }
      # Get and prep the next line to read
      if ( ($get_next_line == 1 ) && (eof(IN) != 1)) {
         $saved_line = <IN>;
         chop $saved_line;
         $real_saved_line = $saved_line;
         @temp_split_line = split(/\b/, $saved_line);
         $saved_line = join(' ', @temp_split_line); 
         @split_line = split(' ', $saved_line);
         @real_split_line = split(' ', $real_saved_line);
      } elsif ( eof(IN) == 1 ) {
         printf "END OF FILE FOUND!!!\n" if $GST_tells_all;
         last;
      }
   }

   printf STDOUT "GST: Snabbed token \"%s\" \n", $localToken if $GST_tells_all;
   $saved_line = join(' ', @split_line);
   $real_saved_line = join(' ', @real_split_line);
   printf STDOUT "GST: --Setting real_saved_line to \"%s\" \n", $real_saved_line if $GST_tells_all;
   printf STDOUT "GST: --Setting saved_line to \"%s\" \n\n", $saved_line if $GST_tells_all;

   return ( $localToken );
}

sub read_cell_libraries {

   
   %libraryCellArray = ();
   local($moveToUpperCase) = $_[0];

   #
   # First, read in any library cell lists
   #
   foreach $libCellFile ( keys(%libraryCellFileArray) ) {
      # first open each file
      if ( !open (LCF, $libCellFile) )  {
         printf STDOUT "Bummer, I can't open library cell file: \"$libCellFile\" \n";
         next; # work on the next source file.
      } else {
         printf STDOUT "\n   Getting library cell list from file \"%s\"\n", $libCellFile if $verbose_mode;
      }
      
      #next read each token
      do {
         $cell_line = <LCF>;
         chomp $cell_line;
         @temp_cell_list = split(/\s+/, $cell_line);
         foreach $atom (@temp_cell_list) {
            if ($moveToUpperCase == 1) {
               $atom = "\U$atom";
            }
            
            if (($atom ne "") && ($libraryCellArray{$atom} != 1) ) {
               $libraryCellArray{$atom} = 1;
               printf STDOUT "      Added library cell \"%s\" \n", $atom if $verbose_mode;
            }
         }
      } until eof(LCF);
   }

}

sub surf_the_verilog_code {
   &set_verilog_defaults;
   &deal_with_HSV_startup_switches;
   &set_up_Verilog();
   &read_cell_libraries(0);
   &parse_Verilog();
   &build_Verilog_design_hier();

   if ( $top_entity eq "" ) {
      &derive_Verilog_hier();
   } else {
      push( @topDesignList, $top_entity);
   }

   &process_each_toplevel_design;
}

sub process_each_toplevel_design {

   $PETD_tells_all = 0;
   printf STDOUT "PETD: in process_each_toplevel_design\n", if $PETD_tells_all;
   foreach $topDesign (@topDesignList) {
      printf STDOUT "   PETD: processing top design \"%s\"", $topDesign, if $PETD_tells_all;
      @topFirstList = ();
      @bottomFirstList = ();
      @missingModuleList = ();
      @indentedUnitList = ();

      # Require that the design have some kids inorder to build the hier...
      $tempOrdinal = $verilogModule_2_counter{ $topDesign };
      $myKidsString = $verilogInstanceList[ $tempOrdinal ];      

      printf STDOUT "\nProcessing the design hierarchy for module \"%s\" and creating scripts...\n", $topDesign if $verbose_mode;
      printf STDOUT   "-------------------------------------------------------------------------\n", $topDesign if $verbose_mode;

      # Build the topDown and bottomsUp lists of entities
      &make_Ordered_Module_Lists($topDesign, 1);
      @bottomFirstList = reverse @topFirstList;

      # Output the desired script files...
      &make_all_Verilog_scripts( $topDesign );
      &make_Verilog_unit_report( $topDesign );
   }
}

sub deal_with_HSV_startup_switches {
   # Debugging switches, basically useless                         
   if ($global_debug == 1) {
      $PV_tells_all = 1;
      $LFMVT2_tells_all = 1;
      $GROVS_tells_all = 1;
      $GVT_tells_all = 1;
      $GNVL_tells_all = 1;
      $BVDH_tells_all = 1;
   } else {
      $PV_tells_all = 0;
      $LFMVT2_tells_all = 0;
   }
   if ($top_entity eq "") {
      printf STDOUT "   No explicit top design given, therefore all parent designs will be derived\n" if $verbose_mode;
   } else {
      printf STDOUT "   Looking for root module \"%s\"\n", $temp_top_entity if $verbose_mode;
   }

   printf STDOUT "\n   Looking for source files in the following directories:\n" if $verbose_mode;
   foreach $source_dir ( @source_dir_list ) {
      printf STDOUT "      \"%s\"\n", $source_dir if $verbose_mode;
   }

   printf STDOUT "\n   Looking for source files with the following extensions:\n" if $verbose_mode;
   foreach $source_ext ( @source_ext_list ) {
      printf STDOUT "      \"%s\" \n", $source_ext if $verbose_mode;
   }

   # Build the list of files the new way
   foreach $source_directory_path ( @source_dir_list ) {
      # Do we need to make this the absolute path now with the -o option?
      foreach $source_extension ( @source_ext_list ) {
	 $glob_pattern = $source_directory_path . "/*." . $source_extension;
	 @dir_file_list = <${glob_pattern}>;
	 foreach $temp_dir_file (@dir_file_list) {
            printf STDOUT "MAIN: Saving target file $s\n", $temp_dir_file if $MAIN_tells_all;
            push (@source_file_list, $temp_dir_file);
	 } 
      }
   }
}

sub set_verilog_defaults {

   if (@source_ext_list == () ) {
      $source_ext_list[0] = "v";
   }
}

sub derive_Verilog_hier {
###########
#
# This fills the topDesignList with target top designs
#
###########

   local ($counter1);
   
   $DVH_tells_all = 0;
   
   printf STDOUT "   DVH: in derive_Verilog_hier\n", if $DVH_tells_all;
   @topDesignList = ();
   # If a merged Unit has no parents, it is a top design...
   for ($counter1 = 0; $counter1 < $fileCounter; $counter1++ ) {
      printf STDOUT "   DVH: Looking at \"%s\"\n", $verilogModuleList[$counter1], if $DVH_tells_all;
      if ( $verilogModuleParentList[$counter1] eq "" ) {
         push( @topDesignList, $verilogModuleList[$counter1]);
         printf STDOUT "   DVH: Added \"%s\" as a top level design\n", $verilogModuleList[$counter1], if $DVH_tells_all;
      }
   }
}

sub build_Verilog_design_hier {
#################
#
# Simply find all childern and parents
#
#  @masterKidList and @masterParentList and $verilogModuleParentList are set in this subroutine...
#
#  8/31/98: Adding library cell list processing var (usedLibraryCellList)
#  5/6/97: improved the debugging messages
#
#################
   local ($myKidString1);
   local ($myKidString2);
   local (@archCompList);
   local ($tempOrd);
   local ($tempComp);
   local ($instancesMissingSource) = 0;
   local (@missingSourceList);
   local ($kid);
   local ($libCellFile);

   @masterKidList = ();
   %usedLibraryCellArray = ();
   @usedLibraryCellList = ();
   $kidListCounter = 0;
   @masterParentList = ();
   $parentListCounter = 0;

   printf STDOUT "\nAttempting to build the hierarchy:\n" if $verbose_mode;
   printf STDOUT   "----------------------------------\n" if $verbose_mode;
   
   #
   # First, build the kid list for all the modules
   #
   printf STDOUT "\nBVDH: Now building kid list\n" if $BVDH_tells_all;
   printf STDOUT "\nBVDH: The master info list is:\n" if $BVDH_tells_all;
   printf STDOUT "------------------------------\n" if $BVDH_tells_all;

   for ($counter1 = 0; $counter1 < $fileCounter; $counter1++ ) {

      @myKidList = split(" ", $verilogInstanceList[$counter1]);

      foreach $kid (@myKidList){

         if ( defined( $verilogModule_2_counter{ $kid } ) ) {
            $masterKidList[$kidListCounter] = $kid;
            $kidListCounter++;

         } elsif ( defined($libraryCellArray{ $kid } ) ) {
            # should put a qualifier here that we haven't seen this before
            push(@usedLibraryCellList, $kid);
            $usedLibraryCellArray{$kid} = 1;
         } else {
            $instancesMissingSource++;
            push(@missingSourceList, $kid);
            push(@missingSourceList, $verilogModuleList[$counter1]);
         }
      }

      # Tag the end of the master kid list for this module
      $masterKidList[$kidListCounter] = "|";
      $kidListCounter++;

      printf STDOUT "   BVDH: My module name is %s\n", $verilogModuleList[$counter1] if $BVDH_tells_all;
      printf STDOUT "   BVDH: My kids names are %s\n", $verilogInstanceList[$counter1] if $BVDH_tells_all;
   }

   if ( $BVDH_tells_all == 1 ) {
      printf STDOUT "\n   BVDH: The master (clean) kid list is:\n";
      printf STDOUT   "   -------------------------------------\n";
      $tempOrd = 0;
      foreach $kid (@masterKidList) {
         printf STDOUT "      Ordinal %d : Kid %s \n", $tempOrd, $kid;
         $tempOrd++;
      }
   }

   #
   # Now, build the parent list for each module
   #
   for ($counter1 = 0; $counter1 < $fileCounter; $counter1++ ) {

      #
      # Look thru the entire list of kids to see who your parents(!) are...
      #
      $tempParentOrdCounter = 0;
      @tempParentList = ();
      printf STDOUT "\n   BVDH: Now looking for the parents of \"%s\"\n", $verilogModuleList[$counter1] if $BVDH_tells_all;
      for($counter2 = 0; $counter2 < $kidListCounter; $counter2++ ){
         printf STDOUT "      BVDH: Am I \"%s\"? \n", $masterKidList[$counter2] if $BVDH_tells_all;
         # If the element is a seperator, count it.
         # Now, use the seperator to tell what ordinal I belong to
         # Then pull that parent name from the $verilogModuleList.
         if ( $masterKidList[$counter2] eq "|" ) {
            # Walked over a parent boundary, so inc the counter...
            $tempParentOrdCounter++;

         # If the module matches the kid...   
         } elsif ( $masterKidList[$counter2] eq $verilogModuleList[$counter1] ) {
            printf STDOUT "      BVDH: Matched \"%s\" to \"%s\" \n", $masterKidList[$counter2], $verilogModuleList[$counter1] if $BVDH_tells_all;
            printf STDOUT "      BVDH: That means \"%s\" is my parent \n",  $verilogModuleList[$tempParentOrdCounter] if $BVDH_tells_all;

            # Save the parent module into the parent list
            $masterParentList[$parentListCounter] = $verilogModuleList[$tempParentOrdCounter];
            $parentListCounter++;

            # and also into a temp list for later usage.
            push( @tempParentList, $verilogModuleList[$tempParentOrdCounter]);
         }
      }

      # create a parent configuration string in the DB...
      $verilogModuleParentList[$counter1] = join ( " ", @tempParentList);
      $masterParentList[$parentListCounter] = "|";
      $parentListCounter++;
      printf STDOUT "   BVDH: My module name is %s\n", $verilogModuleList[$counter1] if $BVDH_tells_all;
      printf STDOUT "   BVDH: My parents names are %s\n", join(" ", @tempParentList) if $BVDH_tells_all;
   }

   if ( $BVDH_tells_all == 1 ) {
      printf STDOUT "\n   BVDH: The master Parent list is:\n";
      printf STDOUT    "   --------------------------------\n";
      $tempOrd = 0;
      foreach $kid (@masterParentList) {
         printf STDOUT "     Ordinal %d : Parent %s \n", $tempOrd, $kid;
         $tempOrd++;
      }

      printf STDOUT "\n   BVDH: The module Parent list is:\n";
      printf STDOUT "   --------------------------------\n";
      for ($counter1 = 0; $counter1 < $fileCounter; $counter1++ ) {
         printf STDOUT "     Child: %20s  Parent: %s \n", $verilogModuleList[$counter1], $verilogModuleParentList[$counter1];
      }
   }

   if ( ($instancesMissingSource > 0) && ($verbose_mode == 1) ) {
      printf STDOUT "Warning:\n" ;
      printf STDOUT "   The source code for the following instance was not found\n" ;
      printf STDOUT "   This might not a big deal, these could be library references! \n" ;
      printf STDOUT "\n   Instances with missing source code:\n" ;
      printf STDOUT   "   ===================================\n" ;
      for ( $counter2 = 0; $counter2 < $instancesMissingSource; $counter2++) {
         $string1 = shift( @missingSourceList );
         $string2 = shift( @missingSourceList );
         printf STDOUT "      Instance \"%s\" in module \"%s\" \n", $string1, $string2 ;
      }
   }
}

sub save_parse_Verilog_info {
###########
#
# 
#
###########

   printf STDOUT "   Saving information for module \"%s\"\n", $moduleName if $verbose_mode;
   $verilogModuleList[$fileCounter] = $moduleName;
   $verilogInstanceList[$fileCounter] = join(" ", @moduleInstanceList);
   $verilogFileList[$fileCounter] = $in;
   $verilogIncludeFileList[$fileCounter] = join(" ", @moduleIncludeList);
   $verilogModule_2_counter{$moduleName} = $fileCounter;
   $verilogModule_2_FileArray{$moduleName} = $in;
   $verilogModule_2_input{$moduleName} = join("|", @moduleInputPortList);
   $verilogModule_2_output{$moduleName} = join("|", @moduleOutputPortList);
   $verilogModule_2_parameter{$moduleName} = join("|", @moduleParameterList);
   #printf STDOUT "SPVI: The input port listing is \"%s\"\n", $verilogModule_2_input{$moduleName};
   #printf STDOUT "SPVI: The output port listing is \"%s\"\n", $verilogModule_2_output{$moduleName};
   #printf STDOUT "SPVI: The parameter listing is \"%s\"\n", $verilogModule_2_parameter{$moduleName};

   printf MDA "%d | %s | %s | %s \n", $fileCounter, $verilogModuleList[$fileCounter],
   $verilogFileList[$fileCounter], $verilogInstanceList[$fileCounter] ;
   $fileCounter++;
   @moduleInstanceList = ();
   $current_Verilog_depth = 0;
}

sub parse_Verilog {
###########
#
# 
#
###########

   local( $inModule );
   local( $searchToken );
   local( $magicVerilogToken );
   local( $instanceName );
   local( $moduleName );
   local( $quoteToken );
   local( $tempToken );
   local( $tempChar );
   local( $tempString );
   local( $tempString2 );
   local( $in );
   local( $mda_base_file );
   local( $mda_file );
   
   if ( @source_file_list == () ) {
      printf STDOUT "\n\n\nSorry dude, I could not find any \"%s\" files, I am outta here... \n", $targetLanguage;
      exit;
   }
   
   # Create the mda (multi-D array) file
   $mda_base_file = ".HS2_MDA";
   $mda_file = $outputDirectory . $mda_base_file;
   open ( MDA, ">$mda_file" );
   printf MDA "HS2: Parse (MDA) output data\n";
     
   # put this in the removal list
   push( @filesToKillList, $mda_base_file);
   push( @filesToKillList, $mda_file);

   @verilogModuleList = ();
   @verilogInstanceList = ();
   @verilogIncludeFileList = ();
   @verilogFileList = ();
   %verilogModule_2_FileArray = ();

   printf STDOUT "\nExamining Verilog files:\n" if $verbose_mode;
   printf STDOUT   "------------------------\n" if $verbose_mode;
   $fileCounter = 0;
   #
   foreach $in ( @source_file_list )  {               

      # set up the loop
       if ( !open (IN, $in) )  {
          printf STDOUT "Bummer, I can't open Verilog source file: \"$in\"\n";
          next; # work on the next source file.
       } else {
          printf STDOUT "\n   Surfing file \"%s\"\n", $in if $verbose_mode;
       }

      printf STDOUT "\n   Parsing Verilog file \"%s\"\n", $in if $verbose_mode;
      $inModule = 0;

      &get_next_Verilog_line;

      @moduleInstanceList = ();
      @moduleIncludeList  = ();
      @moduleInputPortList  = ();
      @moduleOutputPortList  = ();
      @moduleParameterList  = ();
      $current_Verilog_depth = 0;
      
      while ( eof(IN) != 1 ) {
         printf "\nPV: Working on line \"%s\" \n", $saved_line if $PV_tells_all;

         $magicVerilogToken = &look_for_magic_Verilog_token2;

         if ( $magicVerilogToken ne "" ) {      
            printf STDOUT "PV: Found token \"%s\" \n", $magicVerilogToken if $PV_tells_all;

            # this could be moved to look_for_magic_Verilog_token2...
            if ( ($magicVerilogToken eq "wire") || 
                 ($magicVerilogToken eq "assign") || 
                 ($magicVerilogToken eq "reg") || 
                 ($magicVerilogToken eq "=") || 
                 ($magicVerilogToken eq "<=") || 
                 ($magicVerilogToken eq "tri")  
            ) {
               # bleed it out
               printf STDOUT "PV: Found magic token \"%s\", bleeding out line \"%s\" \n", $magicVerilogToken, $master_saved_line if $PV_tells_all;
               $tempToken = &parse_to_end_of_Verilog_statement("PV_wart_bleedout");
               $saved_line = $tempToken . " " . $saved_line;
               printf STDOUT "PV: Module name hunt, bleeding done saved_line is now \"%s\" \n", $saved_line if $PV_tells_all;
            } elsif ( $magicVerilogToken eq "module" ) {

               # Grab the module name
               $moduleName = &get_Verilog_token(1);
               printf STDOUT "      Found module: \"%s\" \n", $moduleName if $verbose_mode;
               $tempToken = &parse_to_end_of_Verilog_statement("PV_module_name");
               $saved_line = $tempToken . " " . $saved_line;
               printf STDOUT "PV: Module name hunt, saved_line is \"%s\" \n", $saved_line if $PV_tells_all;
               $inModule = 1;
            } elsif ( $magicVerilogToken eq "input" ){

               # parse the Input port
               $inputPort_String = &get_rest_of_Verilog_statement;
               chop $inputPort_String;
               printf STDOUT "PV:   Found input port statement:\"%s\"\n", $inputPort_String if $PV_tells_all;
               @splitPortString = split(',', $inputPort_String);
               
               # determine if this is a non-scalar port, and if it is get the width
               $portWidth = "";
               $firstPort = shift(@splitPortString);
               if ( $firstPort =~ /\[/ ) {
                  
                  # Split this first token up further
                  @portWidthList = split(" ", $firstPort);
                  do {
                     $portSubToken = shift(@portWidthList);
                     $portWidth = $portWidth . $portSubToken;
                  } until ($portSubToken =~ /\]/);
                  $portWidth = $portWidth . " ";
                  
                  # reassemble the first port name and push it back on the list
                  $firstPortName = join(" ", @portWidthList);
                  unshift(@splitPortString, $firstPortName);
		  
               } else {
                  unshift(@splitPortString, $firstPort);
					}
               
               # save each port complete with its width
               foreach $port (@splitPortString) {
                  $portName = $portWidth . $port;
                  push(@moduleInputPortList, $portName);
               }
               
               # put an end token in here...
               $saved_line = ";" .$saved_line;
            } elsif ( $magicVerilogToken eq "output" ){

               # Parse the output port
               $outputPort_String = &get_rest_of_Verilog_statement;
               chop $outputPort_String;
               printf STDOUT "PV:   Found output port statement:\"%s\"\n", $outputPort_String if $PV_tells_all;
               @splitPortString = split(',', $outputPort_String);
               
               # determine if this is a non-scalar port, and if it is get the width
               $portWidth = "";
               $firstPort = shift(@splitPortString);
               if ( $firstPort =~ /\[/ ) {
                  
                  # Split this first token up further
                  @portWidthList = split(" ", $firstPort);
                  do {
                     $portSubToken = shift(@portWidthList);
                     $portWidth = $portWidth . $portSubToken;
                  } until ($portSubToken =~ /\]/);
                  $portWidth = $portWidth . " ";
                  
                  # reassemble the first port name and push it back on the list
                  $firstPortName = $portWidthList[$#portWidthList];
                  unshift(@splitPortString, $firstPortName);
               } else {
                  unshift(@splitPortString, $firstPort);
               }
               
               # save each port complete with its width
               foreach $port (@splitPortString) {
                  $portName = $portWidth . $port;
                  push(@moduleOutputPortList, $portName);
               }
               # put an end token in here...
               $saved_line = ";" .$saved_line;
            } elsif ( $magicVerilogToken eq "parameter" ){

               # Parse out the parameter statement
               $parameter_String = &get_rest_of_Verilog_statement;
               chop $parameter_String;
               printf STDOUT "PV:   Found parameter statement:\"%s\"\n", $parameter_String if $PV_tells_all;
               @moduleParameterList = split(',', $parameter_String);
               # put an end token in here...
               $saved_line = ";" .$saved_line;
            } elsif ( $magicVerilogToken eq "endmodule" ){
               printf STDOUT "      Found endmodule, module \"%s\" complete, saving info \n", $moduleName if $verbose_mode;
               $inModule = 0;
               &save_parse_Verilog_info;
               # double reset just to make sure
               @moduleInstanceList = ();
               @moduleIncludeList  = ();
               @moduleInputPortList  = ();
               @moduleOutputPortList  = ();
               @moduleParameterList  = ();
               $current_Verilog_depth = 0;
            } elsif ( $magicVerilogToken eq "`" ){
               $nextTickToken = &get_Verilog_token(1);
               printf STDOUT "      PV: working on tick (`) statement with token \" %s\" in \"%s\"\n", $nextTickToken, $master_saved_line if $PV_tells_all;
               if ( $nextTickToken eq "include" ){
                  # Parse out the include statement
                  $quoteToken = 0;
                  $tempString = "";
                  $tempToken = &get_Verilog_token(1);
                  if ( $tempToken =~ "\"" ) {
                     $tempString = $tempString . $tempToken;
                     $quoteToken++;
                     while ($quoteToken < 2 ) {
                        $tempToken = &get_Verilog_token(1);
                        if ( $tempToken =~ "\"" ) {
                	   $quoteToken++;
                        }
                        $tempString = $tempString . $tempToken;
        	     }
        	     
                     # do a bit of processing
                     chop $tempString;
        	     $tempString2 = reverse($tempString);
                     $char = chop($tempString2);
        	     $tempString = reverse($tempString2);
        	     push( @moduleIncludeList, $tempString);
        	     printf STDOUT "      Found include file \"%s\" \n", $tempString if $verbose_mode;
                     $saved_line = $saved_line . " ;";
                  }
               } else {
                  # parse the rest of the ' line
                  $saved_line = $saved_line . " ;";
                  printf STDOUT "      PV: tick processing with saved_line before \" %s\"\n", $saved_line if $PV_tells_all;
                  $rest_of_tick_line = &get_rest_of_Verilog_statement;
                  
                  # a the semi-colon back on the end
                  $saved_line = $saved_line . " ;";
                  printf STDOUT "      PV: tick processing with saved_line after \" %s\"\n", $saved_line if $PV_tells_all;

               }

            } elsif ( ($inModule == 1 ) && (($magicVerilogToken =~ /\;/) || ($magicVerilogToken =~ /^end/) ) ){
               # This is the instance hunter
               $instanceName = &get_Verilog_token(1);
               printf STDOUT "PV: Hunting instances \n" if $PV_tells_all;
               
               # if this is not a "`" statement, hunt the instances as normal
               if ( ($instanceName ne "`") && ($instanceName ne "\;") ) {

                  printf STDOUT "PV: Looked at saved_line \"%s\" \n", $saved_line if $PV_tells_all;
                  printf STDOUT "PV: Looking at instance \"%s\" \n", $instanceName if $PV_tells_all;
                  if ( (($instanceName ne "endmodule") && ($verilogKeywordsArray{$instanceName} != 1)) ) {

                     # parameter detection bit here...
                     $nextName = &get_Verilog_token(1);
                     printf STDOUT "PV: The nextName is \"%s\"\n", $nextName if $PV_tells_all;
                     
                     # check for and tear out any parameter info
           	     $paramString = "";
        	     if ( $nextName =~ /\#/ ){
        	        printf STDOUT "PV: detected possible parameter on %s \n", $master_save_line if $PV_tells_all; 
        	        printf STDOUT "PV: possible parameter token is %s \n", $nextName if $PV_tells_all; 
        	        do {
        	           $nextName = &get_Verilog_token(1);
           	           printf STDOUT "PV: Pulled possible parameter token is %s \n", $nextName if $PV_tells_all; 
        	           $paramString = $paramString . $nextName;
        	        } until ( $nextName =~ /\)/ );

        	        # message the parameter string a little, reduce to only digits
           	        $paramString =~ s/\)//;
     	                $paramString =~ s/\(//;
        	        $paramString =~ s/\)//;
           	        printf STDOUT "PV: The parameter string is %s \n", $paramString if $PV_tells_all; 

        	        # this should be the real instance name
        	        $nextName = &get_Verilog_token(1);
           	        printf STDOUT "PV: This should be the real instance name token is %s \n", $nextName if $PV_tells_all; 

        	     }

                     # check for an escaped name here
                     if ( $nextName eq "\\") {
        	        $nextName = &get_Verilog_token(1);
                        $nextName = "\\" . $nextName;
                     }

        	     if ( ($verilogKeywordsArray{$instanceName} != 1) && ($inModule == 1 ) 
                          && ($verilogKeywordsArray{$nextName} != 1) && ($instanceName ne "")  
                          && ($nextName ne '[') && ($nextName ne ']' && ($libraryCellArray{$instanceName} !=1 ) ) 
                          ) {
                        
                        $instanceAlreadyFound = 0;
                        
                        printf STDOUT "PV: The value of verilogKeywordsArray{nextName} is \"%s\" \n", $verilogKeywordsArray{$nextName}  if $PV_tells_all;

                        printf STDOUT "PV: Found instance name \"%s\" in line \"%s\"\n", $instanceName, $master_saved_line if $PV_tells_all;
                        printf STDOUT "PV: The cell name is \"%s\"\n", $nextName if $PV_tells_all;
                       # printf STDOUT "         Found instance name \"%s\" (cell name \"%s\") in line \"%s\" \n", $instanceName, $nextName, $master_saved_line if $verbose_mode;
                        printf STDOUT "         Found instance name \"%s\" (cell name \"%s\")\n", $instanceName, $nextName, if $verbose_mode;

                        foreach $tempInstanceName (@moduleInstanceList) {
                	   if ( $tempInstanceName eq $instanceName ) {
                              $instanceAlreadyFound = 1;
                              last;
                	   }
                        }

                        if ( $instanceAlreadyFound == 0 ) {
                	   push( @moduleInstanceList, $instanceName);
                        }
                        
        	        ######################################
                        # should save the 'next_name' as the cell name here
                        # printf STDOUT "PV: Found instance name \"%s\", the cell name is \"%s\" \n", $instanceName, $nextName;
                        $newValue = $instanceName . ":" . $nextName;
                        if ( defined($instanceName_2_CellName{ $moduleName })  ) {
                           $currentIN2PString = $instanceName_2_CellName{ $moduleName };
                           $instanceName_2_CellName{ $moduleName } = $currentIN2PString . " " . $newValue;
                        } else {
                           $instanceName_2_CellName{ $moduleName } = $newValue;
                        }

        	        # should save the 'next_name' as the cell name here
                        # printf STDOUT "PV: Found instance name \"%s\", the cell name is \"%s\" \n", $instanceName, $nextName;
                        $newValue = $moduleName . ":" . $nextName;
                        if ( defined($moduleName_2_moduleCellNames{ $instanceName })  ) {
                           $currentIN2PString = $moduleName_2_moduleCellNames{ $instanceName };
                           $moduleName_2_moduleCellNames{ $instanceName } = $currentIN2PString . " " . $newValue;
                        } else {
                           $moduleName_2_moduleCellNames{ $instanceName } = $newValue;
                        }

                        # Should save any parameter information here (v2.05)
                        # hash: instance name TO parmeter info
                        #   instance-> (list of parent_name:cell_name:parm1:parm2)
                        if ( $paramString ne "" ) {
                           $newValue = $moduleName . ":" . $nextName . ":" . $paramString;
                           if ( defined($instanceName_2_Parameter{ $instanceName })  ) {
                	      $currentIN2PString = $instanceName_2_Parameter{ $instanceName };
                	      $instanceName_2_Parameter{ $instanceName } = $currentIN2PString . " " . $newValue;
                           } else {
                	      $instanceName_2_Parameter{ $instanceName } = $newValue;
                           }
                        }
                        #printf STDOUT "PV: The saved parameter string is \"%s\" \n", $instanceName_2_Parameter{ $instanceName }; 
        	     } elsif ($libraryCellArray{$instanceName} ==1 ) {
                        printf STDOUT "         Found instance of library cell \"%s\" (cell name \"%s\")\n", $instanceName, $nextName;
                     }

        	     $tempToken = &parse_to_end_of_Verilog_statement("PV_instance_hunt_done");
                     $saved_line = $tempToken . " " . $saved_line;
        	     printf STDOUT "PV: after instance name hunt completed, saved_line is \"%s\" \n", $saved_line if $PV_tells_all;

                  } elsif ($instanceName eq "endmodule") {
                     #The last token in the file was the endmodule
                     &save_parse_Verilog_info;
                  } else {
                     #need to push this back into saved_line
                     $saved_line = $instanceName . " " . $saved_line;
        	     printf STDOUT "PV: rejecting instance \"%s\", saved_line is \"%s\" \n", $instanceName, $saved_line if $PV_tells_all;
                  }
               } else {
                  # it is a ` or ;, so push it back and let LFMVT find it
                  $saved_line = $instanceName . " " . $saved_line;
               }
            }
	 }
      } # end of master while loop
      close( IN );
   } # end of master foreach loop
   close( MDA );
}


sub make_Ordered_Module_Lists {
###############
#
# This sub produces the ordered module lists for later usage
# Note that this is a recursive process... 
#
# This was enhanced in v2.22 to use library cells from libaryCellArray 
#
# This also fills the missingInstanceList and indentedUnitList variables...
#
###############
   local ($myName);
   local ($myRealName);
   local ($myLevel);
   local ($nextLevel);
   local ($myLevelName);
   local ($myBlankString);
   local ($myKidsString);
   local ($myTempKid);
   local ($myTempCounter);
   local (@myKidsList);
   local ($myOrdinal);
   
   $MOML_tells_all = 0;
   $myName = $_[0];
   $myLevel = $_[1];
      
   if ( $myLevel == 1 ) {
      $SHF2_string = " ";
   }
   
   $myBlankString = " ";
   # Build the indented string for later usage...
   for ( $myTempCounter = 0; $myTempCounter < $myLevel; $myTempCounter++) {
      $myBlankString = $myBlankString . "   ";
   }
   
   printf STDOUT "\n%sMOML: Called with name \"%s\" and level \"%d\"\n", $myBlankString, $myName, $myLevel if $MOML_tells_all;

   # Need to check if the module is in the list...
   if ( defined($verilogModule_2_counter{ $myName })  ) {
     
      $myOrdinal = $verilogModule_2_counter{ $myName };

      # First, put me in the list
      push (@topFirstList, $myName);
      $SHF2_string = $SHF2_string . " { " . $myName;

      # Now, if I have any kids, call this routine for each of them...
      $myKidsString = $verilogInstanceList[ $myOrdinal ];

      printf STDOUT "%sMOML: The value of myName is \"%s\"\n", $myBlankString, $myName if $MOML_tells_all;
      printf STDOUT "%sMOML: The value of myOrdinal is \"%s\"\n", $myBlankString, $myOrdinal if $MOML_tells_all;
      printf STDOUT "%sMOML: The value of myKidsString is \"%s\"\n", $myBlankString, $myKidsString if $MOML_tells_all;

      if ( $myKidsString ne "" ) {
         $SHF2_string = $SHF2_string . " { ";
         @myKidsList = split(" ", $myKidsString);
         $nextLevel = $myLevel + 1;
         foreach $myTempKid ( @myKidsList ) {
            if ( defined($usedLibraryCellArray{$myTempKid}) ) {
               printf STDOUT "%sMOML: The value of myName is \"%s\", my kid is named \"%s\" is  a library cell\n", $myBlankString, $myName, $myTempKid if $MOML_tells_all;
            } else {  
               printf STDOUT "%sMOML: The value of myName is \"%s\", my kid is named \"%s\"\n", $myBlankString, $myName, $myTempKid if $MOML_tells_all;
               &make_Ordered_Module_Lists($myTempKid, $nextLevel);
            }
         }
         $SHF2_string = $SHF2_string . " } ";
      } else {
         $SHF2_string = $SHF2_string . " {} ";
      }

      if ( defined($instanceName_2_Parameter{ $myName }) ) {
         $myLevelName = $myBlankString . $myName . " (#)";
      } else {
         $myLevelName = $myBlankString . $myName;
      }
      push (@indentedUnitList, $myLevelName);

      # now add the extra info to the SHF string
      $extraInfoString = "";
      $localMERGEOrdinal = $verilogModule_2_counter{ $myName };

      $extraInfoString = $extraInfoString . "Module name     : " . $myName                                    . "\n";
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString . "File name       : " . $verilogModule_2_FileArray{ $myName }      . "\n";
      $extraInfoString = $extraInfoString . "\n";
#      $extraInfoString = $extraInfoString . "Parent designs  : " . $verilogModuleParentList[ $localMERGEOrdinal] . "\n";
      $extraInfoString = $extraInfoString . "Parent designs  : ";
      if ($verilogModuleParentList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(" ", $verilogModuleParentList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
#      $extraInfoString = $extraInfoString . "Sub-designs      : " . $verilogInstanceList[ $localMERGEOrdinal]     . "\n";
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "Sub-designs     : ";
      if ($verilogInstanceList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(" ", $verilogInstanceList[$localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "Sub-design cells: ";
#      $extraInfoString = $extraInfoString . "Sub-design cells: " . $verilogInstanceList[ $localMERGEOrdinal]     . "\n";
      
      if ( defined($instanceName_2_CellName{ $myName } ) ) {
         @cellNamesList = split(" ", $instanceName_2_CellName{ $myName });
         $extraInfoString = $extraInfoString . "(Module name) (Cell name)\n";
         foreach $item (@cellNamesList) {
            $extraInfoString = $extraInfoString . "                  ";
            $extraInfoString = $extraInfoString . $item . "\n";
            # dont do the fancy formatting for now...
            #@paramNamesList = split(':', $item);
            #$extraInfoString = $extraInfoString . $paramNamesList[0] . "   ";
            #$extraInfoString = $extraInfoString . $paramNamesList[1] . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "All module cells: ";
      if ( defined($moduleName_2_moduleCellNames{ $myName } ) ) {
         @cellNamesList = split(" ", $moduleName_2_moduleCellNames{ $myName });
         $extraInfoString = $extraInfoString . "(Parent module name) (Cell name)\n";
         foreach $item (@cellNamesList) {
            $extraInfoString = $extraInfoString . "                  ";
            $extraInfoString = $extraInfoString . $item . "\n";
            # dont do the fancy formatting for now...
            #@paramNamesList = split(':', $item);
            #$extraInfoString = $extraInfoString . $paramNamesList[0] . "   ";
            #$extraInfoString = $extraInfoString . $paramNamesList[1] . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
#      $extraInfoString = $extraInfoString . "Parameters      : " . $instanceName_2_Parameter{ $myName } . "\n";
      $extraInfoString = $extraInfoString .  "Parameters      : ";
      if ( defined($instanceName_2_Parameter{ $myName } ) ) {
         @cellNamesList = split(" ", $instanceName_2_Parameter{ $myName });
         $extraInfoString = $extraInfoString . "(Parent module) (Cell name) (Parameters)\n";
         foreach $item (@cellNamesList) {
            $extraInfoString = $extraInfoString . "                  ";
            @paramNamesList = split(':', $item);
            $extraInfoString = $extraInfoString . $paramNamesList[0] . "   ";
            $extraInfoString = $extraInfoString . $paramNamesList[1] . "   ";
            $extraInfoString = $extraInfoString . $paramNamesList[2] . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
#      $extraInfoString = $extraInfoString .  "Include files   : " . $verilogIncludeFileList[$localMERGEOrdinal]   . "\n";
      $extraInfoString = $extraInfoString .  "Include files   : ";
      if ($verilogIncludeFileList[ $localMERGEOrdinal] ne "" ) {
         @filesNamesList = split(" ", $verilogIncludeFileList[$localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@filesNamesList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
     # $extraInfoString = $extraInfoString .  "Input Ports     : " . $verilogModule_2_input{ $myName }   . "\n";
      $extraInfoString = $extraInfoString .  "Input Ports     : ";
      if ( defined($verilogModule_2_input{ $myName } ) ) {
         @portList = split('\|', $verilogModule_2_input{ $myName });
         $firstItem = 1;
         foreach $item (@portList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "Output ports    : ";
      if ( defined($verilogModule_2_output{ $myName } ) ) {
         @portList = split('\|', $verilogModule_2_output{ $myName });
         $firstItem = 1;
         foreach $item (@portList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
      $extraInfoString = $extraInfoString .  "Parameter names : ";
      if ( defined($verilogModule_2_parameter{ $myName } ) ) {
         @portList = split('\|', $verilogModule_2_parameter{ $myName });
         $firstItem = 1;
         foreach $item (@portList) {
            if ($firstItem == 0) {
               $extraInfoString = $extraInfoString . "                  ";
            } else {
               $firstItem = 0;
            }
            $extraInfoString = $extraInfoString . $item . "\n";
         }
      } else {
         $extraInfoString = $extraInfoString . "\n";
      }
      $extraInfoString = $extraInfoString . "\n";
   } else {
      push( @missingInstanceList, $myName);
      $extraInfoString = "";

      if ( $dont_print_leafs != 1 ) {
         $SHF2_string = $SHF2_string . " { " . $myName . " {} ";
         if ( defined($instanceName_2_Parameter{ $myName }) ) {
            $myRealName = $myName . " (*) (#)";
         } else {
            $myRealName = $myName . " (*)";
         }
         $myLevelName = $myBlankString . $myRealName;
         push (@indentedUnitList, $myLevelName);

	 # now add the extra info to the SHF string
	 $extraInfoString = $extraInfoString .  "Module name     : " . $myName . "\n";
         $extraInfoString = $extraInfoString . "\n";
	 $extraInfoString = $extraInfoString .  "File name       : Unknown\n";
         $extraInfoString = $extraInfoString . "\n";
	# $extraInfoString = $extraInfoString . "Parent designs  : \"" . $verilogModuleParentList[ $localMERGEOrdinal] . "\"\n";
	 $extraInfoString = $extraInfoString .  "Sub-designs     : Unknown\n";
         $extraInfoString = $extraInfoString . "\n";
	 $extraInfoString = $extraInfoString . "Cell names      : ";
	 if ( defined($instanceName_2_CellName{ $myName } ) ) {
            @cellNamesList = split(" ", $instanceName_2_CellName{ $myName });
            $extraInfoString = $extraInfoString . "(Parent module) (Cell name)\n";
            foreach $item (@cellNamesList) {
               $extraInfoString = $extraInfoString . "                  ";
               @paramNamesList = split(':', $item);
               $extraInfoString = $extraInfoString . $paramNamesList[0] . "   ";
               $extraInfoString = $extraInfoString . $paramNamesList[1] . "\n";
            }
	 } else {
            $extraInfoString = $extraInfoString . "\n";
	 }
#         $extraInfoString = $extraInfoString . "Parameters      : " . $instanceName_2_Parameter{ $myName } . "\n";
         $extraInfoString = $extraInfoString . "\n";
         $extraInfoString = $extraInfoString .  "Parameters      : ";
	 if ( defined($instanceName_2_Parameter{ $myName } ) ) {
            @cellNamesList = split(" ", $instanceName_2_Parameter{ $myName });
            $extraInfoString = $extraInfoString . "(Parent module) (Cell name) (Parameters)\n";
            foreach $item (@cellNamesList) {
               $extraInfoString = $extraInfoString . "                  ";
               @paramNamesList = split(':', $item);
               $extraInfoString = $extraInfoString . $paramNamesList[0] . "   ";
               $extraInfoString = $extraInfoString . $paramNamesList[1] . "   ";
               $extraInfoString = $extraInfoString . $paramNamesList[2] . "\n";
            }
	 } else {
            $extraInfoString = $extraInfoString . "\n";
	 }
         $extraInfoString = $extraInfoString . "\n";
	 $extraInfoString = $extraInfoString . "Include files   : Unknown\n";
	 $extraInfoString = $extraInfoString . "\nThe source code for this instance was not found";
      }
   }      

   $SHF2_string = $SHF2_string . " {" . $extraInfoString . " } } ";

}

sub make_Verilog_unit_report {
###############
#
# This sub produces a report for the design Unit
#
#  3/5/98: uniquified the module list
#
#  5/7/97: changed the merged info to be top first
#          Added the "*" at the bottom of the report
#
###############
   local ($myName);
   local ($localName);
   local ($localTopRealName);
   local ($localReportFileName);
   local ($baseReportFileName);
   local ($localUnitList);
   local (%localUnitListArray);
   local ($localMERGEOrdinal);
   
   $myName = $_[0];
   
   $baseReportFileName = $myName . ".unit_report";
   $localReportFileName = $outputDirectory . $baseReportFileName;
   open(REPORT, ">$localReportFileName") || die "HierachySurfer/MUR: Can't open the report file \"$localReportFileName\" for output!\n";
   # Spit up some header information...
   printf REPORT "Design unit report file for root design \"%s\", from HierarchySurfer2 %s!\n\n", $myName, $version;
     
   # put this in the removal list
   push( @filesToCleanList, $baseReportFileName);

   @localUnitList = reverse(@indentedUnitList);
   # First print the Unit listing
   if ( $dont_print_leafs != 1 ) {
      printf REPORT "The top down listing of modules is:\n";
      printf REPORT "-----------------------------------\n";
   } else {
      printf REPORT "The top down listing of modules, without leaf cells, is:\n";
      printf REPORT "--------------------------------------------------------\n";
   }

   foreach $localName (@localUnitList) {
      printf REPORT "   %s\n", $localName;
   }
   printf REPORT "\n   * : This module's source code was not found\n";
   printf REPORT "   # : This module was called with parameters\n";
      
   # For each unit, print all the MERGE info...

   @localUnitList = ();
   %localUnitListArray = ();

   # make the list unique
   foreach $module (@topFirstList){
      if ( !defined( $localUnitListArray{ $module } ) ) {
         $localUnitListArray{ $module } = 1;
         push( @localUnitList, $module);
      }  
   }

   printf REPORT "\nDetailed information for the parsed modules\n";
   printf REPORT   "-------------------------------------------\n";
   foreach $localName (@localUnitList) {
      $localMERGEOrdinal = $verilogModule_2_counter{ $localName };

      printf REPORT "\n   Module \"%s\":\n", $localName ;
      printf REPORT   "   =========================================\n";
      printf REPORT "      Module name            : %s\n", $localName;
      printf REPORT "      File name              : %s\n", $verilogModule_2_FileArray{ $localName };
#      printf REPORT "      Parent designs         : %s\n", $verilogModuleParentList[ $localMERGEOrdinal];
      printf REPORT "      Parent designs         :";
      if ( $verilogModuleParentList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(" ", $verilogModuleParentList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $spaceString = "                              ";
            } else {
               $firstItem = 0;
               $spaceString = "";
            }
            printf REPORT " %s%s\n", $spaceString, $item;
         }
      } else {
         printf REPORT "\n";
      }
#      printf REPORT "      Sub-designs            : %s\n", $verilogInstanceList[ $localMERGEOrdinal];
      printf REPORT  "      Sub-designs            :";
      if ( $verilogInstanceList[ $localMERGEOrdinal] ne "" ) {
         @cellNamesList = split(" ", $verilogInstanceList[ $localMERGEOrdinal]);
         $firstItem = 1;
         foreach $item (@cellNamesList) {
            if ($firstItem == 0) {
               $spaceString = "                              ";
            } else {
               $firstItem = 0;
               $spaceString = "";
            }
            printf REPORT " %s%s\n", $spaceString, $item;
         }
      } else {
         printf REPORT "\n";
      }
#      printf REPORT "      Cell Names             :%s\n", $instanceName_2_CellName{ $localName };
      printf REPORT "      Cell names               Parent module:Cell name";
      if ( defined($instanceName_2_CellName{ $localName } ) ) {
         printf REPORT  "\n";
         @cellNamesList = split(" ", $instanceName_2_CellName{ $localName });
         foreach $item (@cellNamesList) {
            $spaceString = "                             : ";
            printf REPORT "%s%s\n", $spaceString, $item;
         }
      } else {
         printf REPORT "\n";
      }
#      printf REPORT "      Parameters             : %s\n", $instanceName_2_Parameter{ $localName };
      printf REPORT  "      Parameters               Parent module:Cell name:Parameters";
      if ( defined($instanceName_2_Parameter{ $localName } ) ) {
         printf REPORT  "\n";
         @cellNamesList = split(" ", $instanceName_2_Parameter{ $localName });
         foreach $item (@cellNamesList) {
            $spaceString = "                             : ";
            printf REPORT "%s%s\n", $spaceString, $item;
         }
      } else {
         printf REPORT "\n";
      }
      printf REPORT "      Include files          : %s\n", $verilogIncludeFileList[$localMERGEOrdinal];
   }
   
   # Finish with the list of possibly missing components...
   if ( @missingInstanceList != () ) {
      printf REPORT "\nThe list of instances with missing source code is:\n";
      printf REPORT   "--------------------------------------------------\n";
      foreach $localName (@missingInstanceList) {
	 printf REPORT "   %s\n", $localName;
      }
   }
}

sub get_Verilog_token {
#################
#
# saved_line must be set! 
# 
#################
   local ( $number_of_tokens );
   local ( $get_next_line );
   local ( $myLocalToken );
   local ( $offset );
   local ( $tempChar );
   local ( $tempChar );
   
   $offset = $_[0];
   
   $number_of_tokens = 0;
   @split_line = split(" ", $saved_line);
   printf STDOUT "   GVT: Starting with saved_line \"%s\"\n", $saved_line, if $GVT_tells_all;
   
   #while ( ($number_of_tokens < $offset) && (eof(IN) != 1) ) {
   
   # moved the end of file loop cancelation closer to detection because there
   # can be a case where the file point is at EOF, but there are still valid tokens
   while ( $number_of_tokens < $offset ) {
      $get_next_line = 0;
      $myLocalToken = shift( @split_line );
      printf STDOUT "   GVT: working on token \"%s\"\n", $myLocalToken, if $GVT_tells_all;
      # removed the "//" hunt because all lines are preconditioned now since v2.20
      if ($myLocalToken =~ /\/\*/ ){
         # multi-line comment start
         printf "GVT: In multi-line comment field\n" if $GVT_tells_all;
         while ( !($myLocalToken =~ /\*\//) ) {
            $get_next_line = 0;
            $myLocalToken = shift( @split_line );
            if ( $myLocalToken eq "" ) {
               $get_next_line = 1;               
            }
            if ( ($get_next_line == 1 ) && (eof(IN) != 1)) {
               printf STDOUT "GVT: Getting next Verilog line\n", if $GVT_tells_all;
               &get_next_Verilog_line;
	    } elsif ( eof(IN) == 1 ) {
               printf "GVT: EOF found in multi-line comment, returning!!!\n" if $GVT_tells_all;
               return "";
	    }
         }
         printf "GVT: Out multi-line comment field\n" if $GVT_tells_all;
      } elsif ( $myLocalToken =~ /"/ ) {
          if ( $current_Verilog_depth > 0 ) {
             #
             #  Must parse to the next " token here
             printf "GVT: In quote field, Depth is %s\n", $current_Verilog_depth  if $GVT_tells_all;
             printf "GVT: Local token is  \'%s\'\n", $myLocalToken if $GVT_tells_all;
             printf "GVT: Found \'\"\' character in token \'%s\' on saved_line \'%s\'\n", $myLocalToken, $saved_line if $GVT_tells_all;
             $myLocalToken = shift( @split_line );
             while ( (!($myLocalToken =~ /"/)) && ($myLocalToken ne "") ) {
                printf "GVT: Shifting split_line, now local token is  \'%s\'\n", $myLocalToken if $GVT_tells_all;
                $myLocalToken = shift( @split_line );
             }
             $saved_line = join(' ', @split_line);
             printf "GVT: Out quote field\n"  if $GVT_tells_all;
             printf "GVT: Saved_line is now\'%s\'\n", $saved_line if $GVT_tells_all;
          } else {
             $number_of_tokens++;
          }
      } elsif ( $myLocalToken ne "" ) {
         # Real token, count it
         $number_of_tokens++;
         printf STDOUT "GVT: found legal token \"%s\", the current token count is \"%s\"\n", $myLocalToken, $number_of_tokens, if $GVT_tells_all;
      } else {
         $get_next_line = 1;               
      }

      # Get and prep the next line to read
      if ( ($get_next_line == 1 ) && (eof(IN) != 1)) {
         printf STDOUT "GVT: Getting next Verilog line\n", if $GVT_tells_all;
         &get_next_Verilog_line;
      } elsif ( (eof(IN) == 1) && ($number_of_tokens < $offset) ) {
         printf "GVT: EOF found while looking for next line, returning!!!\n" if $GVT_tells_all;
         return "";
      }
   }

   printf STDOUT "GVT: Snabbed token \"%s\" \n", $myLocalToken if $GVT_tells_all;
   $saved_line = join(' ', @split_line);
   return ( $myLocalToken );
}

sub get_next_Verilog_line {
###############################
#
# This simply gets the rest of the Verilog line
#
###############################

   if (eof(IN) != 1) {
      $saved_line = <IN>;
      
      $tempChar = chop($saved_line);
      if ( $tempChar ne "\n" ) {
	 $saved_line = $saved_line . $tempChar;
	 printf STDOUT "GNVL: Pushed back the character \"%s\" on line \"%s\" \n", $tempChar, $saved_line if $GNVL_tells_all;
      }

      # add some line conditioning to remove escaped quotes
      $saved_line =~ s/\\\"//g;
      $master_saved_line = $saved_line;
      
      # remove comments (incl imbedded comments from line)
      #printf STDOUT "GNVL: saved_line before : \"%s\"\n", $saved_line;
      
      # this sub didn't seem to work...
      #$saved_line =~ s/\/\//$`/;
      
      # do it by hand...
      if ($saved_line =~ m/\/\//) {
         $saved_line = $`;
      }
      #printf STDOUT "GNVL: in front of the pattern : \"%s\" \n", $` ;
      #printf STDOUT "GNVL: in back of the pattern : \"%s\" \n", $' ;

      # $saved_line =~ s/^(.*)\/\/.*/$1/g;
      #printf STDOUT "GNVL: saved_line after : \"%s\"\n", $saved_line;
      
      @temp_split_line = split(/\b/, $saved_line);
      $saved_line = join(' ', @temp_split_line); 
      @split_line = split(' ', $saved_line);
      printf STDOUT "GNVL: Returning line \"%s\" \n", $saved_line if $GNVL_tells_all;
   }

}

sub look_for_magic_Verilog_token2 {
##########################
#
# An all important subroutine!
# This looks thru the list given by the magic_word_list and
# returns the found token from that list
#
# It also reforms the saved_line so that later parsing start
# from the right spot...  Think about it...
#
# The Following GLOBAL VARIABLES ARE USED and changed
#
#   split_line : list
#   saved_line : String
#
#  saved_line must be set!
#   
##########################
   local ( $previousToken );
   local ( $localToken );
   local ( $foundMagicToken );
   local ( $foundEndToken );
   local ( $returnToken );
   local ( $depthCounter ) = 0;
   local ( $tempToken1 );
   local ( $tempToken2 );
   local ( @temp_split_line );
   local ( $magic_word );
   local ( $end_word );
   local ( @magic_token_list );
   local ( @end_token_list );

   # Prep the search
   $foundMagicToken = 0;
   
   # Modified in v2.25 to include = and <= 
   # Modified in v2.09 to include input, output and parameter for detection
   # Modified in v2.17 to add ` for that crap,  removed include 
   @magic_token_list = ( 'begin', 'end', 'module',  'case', 
                         'casex', 'casez', '\;', 'function', 'specify', 
                         'define', 'input', 'output', 'parameter',
                         '=', '<=',
                         'wire', 'reg', 'tri', '`', 'assign' ); 
                          
   # Added in v1.07.  This is the list of all legal end keywords...
   # in v2.03 removed endif, added by in v2.09
   @end_token_list = ( 'end', 'endmodule', 'endspecify', 'endcase', 
                        'endfunction', 'endprimative', 'endtask',
                        'endtable', 'endif');
   
   # 8/13/96 v1.0b1 fix to split the first line properly...
   @temp_split_line = split(/\b/, $saved_line);
   $saved_line = join(' ', @temp_split_line); 

   while ( eof(IN) != 1 ) {   
      printf STDOUT "   LFMVT2: Magic token hunt now looking at line: \"%s\"\n", $saved_line if $LFMVT2_tells_all;

      # added in v2.03
      $previousToken = $localToken;
      $localToken = &get_Verilog_token( 1 );
      printf STDOUT "   LFMVT2: Looking at token \"%s\" \n", $localToken if $LFMVT2_tells_all;
      $foundMagicToken = 0;
      foreach $magic_word ( @magic_token_list ) {
         # this is a partial match
         if ( $localToken =~ /$magic_word/ ) {
            printf STDOUT "      LFMVT2: magic_word \"%s\" close to localToken \"%s\" \n", $magic_word, $localToken if $LFMVT2_tells_all ;
             
            # enhanced to do better end detection in v1.07
            if ( $magic_word eq "end" ) {
               $foundEndToken = 0;
               foreach $end_word ( @end_token_list ) {
                  # Do an exact match here! 
                  if  ($localToken eq $end_word) {
                     $foundEndToken = 1;
                     last;
                  }
               }
               if ($foundEndToken == 1) {
                  $foundMagicToken = 1;
                  last;
               }
            } else {
               # This means at least a partial match was found
               $foundMagicToken = 1;
               last;
            }
         }
      }
      
      # If a magic token was found, process it, otherwise continue
      if ( $foundMagicToken == 1 ) {
         printf STDOUT "   LFMVT2: magic_token \"%s\" found\n", $localToken if $LFMVT2_tells_all ;
         if ($localToken eq "specify" ){
            # blow off specify blocks
            $previousToken = $localToken;
            $localToken = &get_Verilog_token( 1 );
            printf STDOUT "\nLFMVT2: In specify block, parsing to endspecify\n" if $LFMVT2_tells_all;
            while ( eof(IN) != 1 ) {
               if ($localToken eq "endspecify" ) {
                  last;
               }
               $previousToken = $localToken;
               $localToken = &get_Verilog_token( 1 );
            }
         # this is commented out due to the improves in quote detection in v2.05
         #} elsif ( $localToken eq 'endmodule')  {
            # we needed a condition here to handle depthcounter problems.
         #   $returnToken = $localToken;
         #   last;            
         } else {
            # 9/6 modified case compare to catch casez and casex
            if ( ($localToken eq 'begin') || ($localToken eq 'case' ) || ($localToken eq 'function' ) 
                 || ($localToken eq 'casex' ) || ($localToken eq 'casez' ) ) {
               $depthCounter++;
               $current_Verilog_depth = $depthCounter;
               printf STDOUT "\nLFMVT2: The down token is %s\n", $localToken if $LFMVT2_tells_all;
               printf STDOUT "LFMVT2: The saved_line is %s\n", $master_saved_line if $LFMVT2_tells_all;
               printf STDOUT "LFMVT2: The depth is now %d\n", $depthCounter if $LFMVT2_tells_all;
            # do we need to put endif here also?
            } elsif ( ($localToken eq 'end')  || ($localToken eq 'endcase' ) || ($localToken eq 'endfunction' ) ) {
               $depthCounter--;
               $current_Verilog_depth = $depthCounter;
               printf STDOUT "\nLFMVT2: The up token is %s\n", $localToken if $LFMVT2_tells_all;
               printf STDOUT "LFMVT2: The saved_line is %s\n", $master_saved_line if $LFMVT2_tells_all;
               printf STDOUT "LFMVT2: The depth is now %d\n", $depthCounter if $LFMVT2_tells_all;

               # added  9/10 to fix detection of module after end without semicolon...
               if ($depthCounter <= 0 ) {
                 $returnToken = $localToken;
                 last;
               }
            } elsif ( $localToken eq 'define')  {
               printf STDOUT "LFMVT2: Found a define statement start, the token is %s\n", $localToken if $LFMVT2_tells_all;
               # Eat the rest of the line here...
               &get_next_Verilog_line;
               
               # fake parse_verilog into thinking this is an end of line
               $returnToken = "\;";
               last;

            } elsif ( $depthCounter == 0 )  {
#              if ( $localToken ne 'endmodule' ) {
                  $returnToken = $localToken;
                  last;
#              }
            }
         }
      }
   }
   printf STDOUT "LFMVT2: Returning token \"%s\", at depth \"%s\"\n", $returnToken, $depthCounter if $LFMVT2_tells_all;
   return ( $returnToken );
}

sub make_all_Verilog_scripts {
###############
#
#
#
###############
   
   local  ($baseName);
   local  ($tempName);
   local  ($tempOrd);
   local  ($dirtyHier);
   
   $baseName = $_[0];
   
   $dirtyHier = 0;
   # Vomit out the list of modules in this design...
   printf STDOUT "   This design contains the following modules \n" if $verbose_mode;
   foreach $tempName ( @bottomFirstList ) {
      printf STDOUT "      Module: \"%s\" \n", $tempName if $verbose_mode;
   }

   # Make a file for DesignSufer to display
   $SHFFileName = $baseName . ".shf";
   &make_Verilog_SHF_file( $SHFFileName );
      
   # Make a DesignCompiler analyze/elaborate script
   $dcFileName = $baseName . ".scr";
   &make_Verilog_DC_script( $dcFileName );

   # Make a simple DC make file...
   $dcFileName = $outputDirectory . "Makefile_" . $baseName . ".dc";
#   &make_Verilog_DC_makefile( $dcFileName );

   # Make a HDL Advisor scripts (a setup file and a ha_shell file)
   $hdlaSetupFileName = $baseName . "_ha.setup";
   $hdlaShellFileName = $baseName . "_ha.shell";
   &make_Verilog_HDLA_script( $hdlaSetupFileName, $hdlaShellFileName, $baseName );
}

sub make_Verilog_HDLA_script {
#################
#
# Will not break on case anymore, I think...
# Trying to enhance to combine files in case of multiple source files... 
# This is done to get around STAR 26393
#
# This also creates a list of combined files that the unit_report file spits out
#
#################
   local ($localHDLASetupFile);
   local ($localHDLAShellFile);
   local ($baseHDLASetupFile);
   local ($baseHDLAShellFile);
   local ($tempObject1);
   local ($tempObject2);
   local ($topObject);
   local ($analyzeFileName);
   local ($realTopEntity);
   local ($tempEntity);
   local ($tempString);
   local ($tempOrdinal);
   local ($tempOutputFileName);
   local ($entityNotInList);
   local (@tempList);
   local ($tempPackage);
   local ($tempEN);
   local ($localTopDesign);
   local (@processedEntityList);
   local (%processedFileArray);
   
   @combinedFileList = ();
   
   $baseHDLASetupFile = $_[0];
   $baseHDLAShellFile = $_[1];
   $localHDLASetupFile = $outputDirectory . $baseHDLASetupFile;
   $localHDLAShellFile = $outputDirectory . $baseHDLAShellFile;
   $localTopDesign     = $_[2];
   
   # Open wide
   open(HDLASU, ">$localHDLASetupFile") || die "MVF: Can't open the HDLA setup file \"$localHDLASetupFile\" for output!\n";
   open(HDLASH, ">$localHDLAShellFile") || die "MVF: Can't open the HDLA ha_shell file \"$localHDLAShellFile\" for output!\n";
     
   # put this in the removal list
   push( @filesToCleanList, $baseHDLASetupFile);
   push( @filesToCleanList, $baseHDLAShellFile);
   
   # Print standard crap for the ha_shell file
   printf HDLASH "/* \n";
   printf HDLASH "   Ha_shell script, automagically generated from HierarchySurfer-Verilog %s \n", $version;
   printf HDLASH "\n   The following lines contain script defaults  \n";
   printf HDLASH "   gtech_directory   : Directory for \".ha\", \".bi\", and \".id\" files \n";
   printf HDLASH "   library_directory : The physical location of logical library ADVISOR_LIB\n";
   printf HDLASH "*/\n";
   printf HDLASH "gtech_directory = \".\" \n";
   printf HDLASH "library_directory = \".\" \n";
   printf HDLASH "hdlin_advisor_directory = gtech_directory\n";
   printf HDLASH "define_design_lib ADVISOR_LIB -path library_directory\n";

   printf HDLASH  "\n";
   printf HDLASH  "\/* Analyze the design units */\n";

   $tempOrdinal = $verilogModule_2_counter{ $localTopDesign };

   # Now, make a project (setup) file for this design...
   printf HDLASU "\# Created by HierarchySurfer %s \n\n", $version;
   printf HDLASU "\# -------------------------------------------------------------------- \n"; 
   printf HDLASU "\# 		 HDL Advisor Project File for design : \"%s\"  \n", $localTopDesign ;
   printf HDLASU "\# --------------------------------------------------------------------  \n";
   printf HDLASU "set  ha_handle_multiple_instances \" auto_uniquify \" \n";
   printf HDLASU "set  ha_top_design_name 	\" %s \" \n", $localTopDesign ;
   $tempOutputFileName = $localTopDesign . ".ha";
   printf HDLASU "set  ha_gtech_top_db_file 	\" %s \" \n", $tempOutputFileName ;

   # Print the source directories, as used in the parse process
   printf HDLASU "set  ha_search_path 	\" \\ \n" ;
   foreach $source_dir ( @source_dir_list ) {
      printf HDLASU "  %s \\ \n", $source_dir;
   }
   printf HDLASU "  \" \n";

   # Print the source directories
   printf HDLASU "set  ha_gtech_db_files  \"  \\ \n" ;

   $entityNotInList = 1;
     
   # First, write the ha_shell part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         $topObject = $tempObject1;
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $verilogModule_2_counter{ $tempObject1 };
         $tempString = $verilogFileList[ $tempOrdinal ];
      
         if ( !defined ( $processedFileArray{$tempString}) ) {
            printf HDLASH  "analyze -w ADVISOR_LIB -f verilog %s\n", $tempString;
            $processedFileArray{$tempString} = "make_HDLA_script problem!!";
         } 
      }
   }

   # Elaborate the top design
   printf HDLASH "\n/* elaborate from the top design */\n";
   printf HDLASH "elaborate -w ADVISOR_LIB %s\n", $localTopDesign;
   printf HDLASH "\nuniquify\n";

   printf HDLASH "\n/* Save all the designs into the gtech_directory */\n";
   printf HDLASH "advisor_output_file = gtech_directory + \"/\" + \"%s\" + .ha\n", $localTopDesign;
   printf HDLASH "write -h -output advisor_output_file\n\n";

   $tempOutputFileName = $localTopDesign . ".ha";
   printf HDLASU "  %s \\ \n", $tempOutputFileName;
 
   printf HDLASH "quit\n";
   close HDLASH;

   printf HDLASU "  \" \n";
  

   close HDLASU;
}

sub make_Verilog_DC_script {
###########
#
# Make an analyze/elaborate script...
#
#  By default, only the top level entity is elab'ed
#
###########
   local ($localDCFilename);
   local ($tempObject1);
   local ($tempObject2);
   local ($tempPackage);
   local ($tempEntity);
   local ($tempString);
   local ($tempOrdinal);
   local ($tempOutputFileName);
   local ($entityNotInList);
   local (@tempList);
   local (@processedEntityList);
   local ($lastOne);
   local (%processedFileArray);

   $baseDCFilename = $_[0];
   $localDCFilename = $outputDirectory . $baseDCFilename;

   open(DC, ">$localDCFilename") || die "MDF: Can't open the DC file \"$localDCFilename\" for output!\n";
     
   # put this in the removal list
   push( @filesToCleanList, $baseDCFilename);

   # Print standard crap   
   printf DC "/*  \n";
   printf DC "   Design Compiler Verilog analyze/elaborate script. \n";
   printf DC "   automagically generated from HierarchySurfer-Verilog %s \n\n", $version;
   printf DC "\n   The following lines contain script defaults  \n";
   printf DC "   dc_file_path : The directory to put the elaborated \".db\" files \n";
   printf DC "   library_path : The directory to store the analyzed files \n";
   printf DC "*/ \n";
   printf DC "\ndc_file_path = \".\" \n";
   printf DC "library_path = \".\" \n";
   
   # print out the search_path include the source dirs, needed for 'include files 
   printf DC "\nsearch_path = search_path + {\\\n";
   foreach $source_dir ( @source_dir_list ) {
      printf DC "  %s \\\n",  $source_dir;
   }
   printf DC "}\n";

   printf DC "\ndefine_design_lib WORK -path library_path\n";

   printf DC  "\n";
   printf DC  "/* Analyze the design units */ \n";

   $entityNotInList = 1;
     
   # First, write the analyze part
   foreach $tempObject1 ( @bottomFirstList ) {
      $entityNotInList = 1;
      # Make sure that we have not processed this bit already...
      foreach $tempObject2 ( @processedEntityList ) {
         if ( $tempObject2 eq $tempObject1 ) {
            $entityNotInList = 0;
            last;
         }
      }
      
      if ( $entityNotInList )  {
         # Add this to the list
         push( @processedEntityList, $tempObject1);
         
         # Get the list of files that are needed to build this entity
         $tempOrdinal = $verilogModule_2_counter{ $tempObject1 };
         $tempString = $verilogFileList[ $tempOrdinal ];
      
         if ( !defined ( $processedFileArray{$tempString}) ) {
            printf DC  "analyze -w WORK -f verilog %s\n", $tempString;
            # This prevents the file from being analyzed twice.
            $processedFileArray{$tempString} = "make_Verilog_DC_script problem!!";
         } 
          
         $lastOne = $tempObject1;
      }
   }

   # This should get the top unit...
   if ($elab_each_unit == 0) {
      printf DC "\n/* Elaborate the top unit only */\n";
      printf DC "elaborate -w WORK %s\n", $lastOne;
      printf DC "dc_elab_file = dc_file_path + \"/\" + \"%s\" + .db\n", $lastOne;
      printf DC "write -h -output dc_elab_file\n\n";
   }
   
   printf DC "quit\n";
   close DC;
}

sub make_Verilog_SHF_file {
###########
#
# Create the Standard Hierarchy Format for DesignSurfer2
#
###########
   local ($localGraphFileName );
   local ($baseGraphFileName );
   
   $baseGraphFileName = $_[0];
   $localGraphFileName = $outputDirectory . $baseGraphFileName;
   push( @SHFFiles, $baseGraphFileName );

   open(SHF, ">$localGraphFileName") || die "MSHFF: Can't open the SHF file \"$localGraphFileName\" for output!\n";
     
   # put this in the removal list
   push( @filesToCleanList, $baseGraphFileName);
   
   printf SHF "\# Standard Hierarchy Format v2.0 file \n";  
   printf SHF "\# Spewed forth from HS2(%s)!\n\n", $version;  
   printf SHF "set DSArray(surfDir) %s \n", $surfDir;  
   printf SHF "set DSArray(surfDate) \"%s\" \n", $surfDate;  
   printf SHF "set HSList {%s} \n", $SHF2_string;  
   $entityNotInList = 1;

   close SHF;
}

sub set_up_Verilog {
###########
#
# 
#
###########

%verilogKeywordsArray = (
'always', '1',
'and', '1',
'assign', '1',
'begin', '1',
'buf', '1',
'bufif0', '1',
'bufif1', '1',
'case', '1',
'casex', '1',
'casez', '1',
'cmos', '1',
'deassign', '1',
'default', '1',
'defparam', '1',
'define', '1',
'disable', '1',
'else', '1',
'end', '1',
'endcase', '1',
'endif', '1',
'endfunction', '1',
'endmodule', '1',
'endprimitive', '1',
'endspecify', '1',
'endtable', '1',
'endtask', '1',
'event', '1',
'for', '1',
'force', '1',
'forever', '1',
'fork', '1',
'function', '1',
'highz0', '1',
'highz1', '1',
'if', '1',
'ifdef', '1',
'initial', '1',
'inout', '1',
'input', '1',
'integer', '1',
'join', '1',
'large', '1',
'medium', '1',
'module', '1',
'nand', '1',
'negedge', '1',
'nmos', '1',
'nor', '1',
'not', '1',
'notif0', '1',
'notif1', '1',
'or', '1',
'output', '1',
'parameter', '1',
'pmos', '1',
'posedge', '1',
'primitive', '1',
'pulldown', '1',
'pullup', '1',
'pull0', '1',
'pull1', '1',
'rcmos', '1',
'reg', '1',
'real', '1',
'release', '1',
'repeat', '1',
'rnmos', '1',
'rpmos', '1',
'rtran', '1',
'rtranif0', '1',
'rtranif1', '1',
'scalared', '1',
'small', '1',
'specify', '1',
'strong0', '1',
'strong1', '1',
'supply0', '1',
'supply1', '1',
'supply1', '1',
'table', '1',
'task', '1',
'time', '1',
'tran', '1',
'tranif0', '1',
'tranif1', '1',
'tri', '1',
'triand', '1',
'trior', '1',
'trireg', '1',
'tri0', '1',
'tri1', '1',
'vectored', '1',
'wait', '1',
'wand', '1',
'weak0', '1',
'weak1', '1',
'while', '1',
'wire', '1',
'wor', '1',
'xnor', '1',
'xor', '1',
'/*', '1',
'*/', '1',
'=', '1',
'\,', '1',
'\`', '1',
'`', '1',
'\'', '1',
'<=', '1',
'>=', '1',
'\{', '1',
'(', '1',
'$', '1',
')', '1',
'(,', '1',
'),', '1',
'[,', '1',
'],', '1',
'\[,', '1',
'\],', '1',
',', '1',
':', '1',
'<', '1',
'>', '1',
'#', '1',
'.', '1',
'&', '1'
);

}

###########################################
#
# New subs for HS2 below
#
###########################################

sub process_HS2_command_line {
   $MAIN_tells_all = 0;
   printf STDOUT "ARGV[0] is \"%s\"\n", $ARGV[0] if $MAIN_tells_all;
    
   # Process command_line switches
   while ($ARGV[0] =~ /^-/) {
	 $_ = shift(@ARGV);
	 $ttoken = $_;
         printf STDOUT "Pulled token %s out of command line \n", $ttoken if $MAIN_tells_all;
         if (/^-d(.*)/) {
            $dir = ($1 ? $1 : shift(@ARGV));
            $_ = $dir;
            if ((/^-/) || ($_ eq "" ) ) {
               unshift( @ARGV, $_ );
            } else {
               printf STDOUT "DIR: Pulled first token %s out of command line \n", $dir if $MAIN_tells_all;
               do {
                  printf STDOUT "DIR: Pulled token %s out of command line \n", $_ if $MAIN_tells_all;
                  $source_dir_list[$dir_counter++] = $_;
                  $_ = ($1 ? $1 : shift(@ARGV));
               } until ((/^-/) || ($_ eq "" ) );
               printf STDOUT "DIR: Last token %s from command line \n", $_ if $MAIN_tells_all;
               unshift( @ARGV, $_ );
            }
         } elsif (/^-e(.*)/) {
            $dir = ($1 ? $1 : shift(@ARGV));
            $_ = $dir;
            if ((/^-/) || ($_ eq "" ) ) {
               unshift( @ARGV, $_ );
            } else {
               do {
                  $source_ext_list[$ext_counter++] = $_;
                  $_ = ($1 ? $1 : shift(@ARGV));
               } until ((/^-/) || ($_ eq "" ) );
               unshift( @ARGV, $_ );
            }
         } elsif (/^-x(.*)/) {
            # v1.0b4 file exclusion feature
            $fileExclusion = 1;
            $dir = ($1 ? $1 : shift(@ARGV));
            $_ = $dir;
            if ((/^-/) || ($_ eq "" ) ) {
               unshift( @ARGV, $_ );
            } else {
               do {
                  $fileExclusionArray{$_} = 1;
                  printf STDOUT "DIR: File \"%s\" is in the fileExclusionArray\n", $_ if $MAIN_tells_all;
                  $_ = ($1 ? $1 : shift(@ARGV));
               } until ((/^-/) || ($_ eq "" ) );
               unshift( @ARGV, $_ );
            }
         } elsif (/^-c(.*)/) {
            # v2.22 library cell file(s) reading list
            # printf STDOUT "Hey... this option is not yet supported! \n";
            $dir = ($1 ? $1 : shift(@ARGV));
            $_ = $dir;
            if ((/^-/) || ($_ eq "" ) ) {
               unshift( @ARGV, $_ );
            } else {
               do {
                  $libraryCellFileArray{$_} = 1;
                  printf STDOUT "DIR: File \"%s\" is in the libraryCellFileArray\n", $_ if $MAIN_tells_all;
                  $_ = ($1 ? $1 : shift(@ARGV));
               } until ((/^-/) || ($_ eq "" ) );
               unshift( @ARGV, $_ );
            }
         } elsif (/^-D(.*)/) {
            $global_debug = 1;
            printf STDOUT "Hey... you used the hidden \"-D\" switch! \n";
            $global_debug_value = ($1 ? $1 : shift(@ARGV));
            if ($global_debug_value =~ /^-/) {
              unshift( @ARGV, $global_debug_value );
            }

         } elsif (/^-t(.*)/) {
            $top_entity = ($1 ? $1 : shift(@ARGV));
         } elsif (/^-o(.*)/) {
            $outputDirectory = ($1 ? $1 : shift(@ARGV));
            # this crap is to check for a closing /
            @ODCharList = split(//,$outputDirectory);
            @ODRCL = reverse @ODCharList;
            if ( $ODRCL[0] ne "/" ) {
               printf STDOUT "Added a / onto \"%s\" \n", $outputDirectory;
               $outputDirectory = $outputDirectory . "/";
            }
         } elsif (/^-l(.*)/) {
                 $targetLanguage = ($1 ? $1 : shift(@ARGV));
                 #ENHANCEMENT NEEDED HERE to be less strict
         } elsif (/^-z(.*)/) {
                 printf STDOUT "\n%s\n", $numericVersion;
                 exit;
         } elsif (/^-v(.*)/) {
                 $verbose_mode = 1;
                 printf STDOUT "  Setting verbose mode\n";
         } elsif (/^-h(.*)/) {
                 print STDOUT $usage_message;
                 exit;
         } elsif (/^-s(.*)/) {
                 $elab_each_unit = 1;
         } elsif (/^-n(.*)/) {
                 $dont_print_leafs = 1;
         } elsif (/^-c(.*)/) {
                 $make_cyclone = 1;
                 printf STDOUT "\"-c\" What the... How did you know about this?! \n";
         } elsif (/^-u(.*)/) {
                 $removeTempFiles = 0;
                 printf STDOUT "\"-u\" Wait a minute, how did you know about this?! \n";
         } elsif (/^-p(.*)/) {
                 $write_packages = 0;
                 printf STDOUT "Hey... you used a hidden switch! \n";
         } elsif (/^-b(.*)/) {
                 $process_single_designs = 0;
                 printf STDOUT "Okay, hey wait, did you use a hidden switch?!? \n";
         } elsif (/^-w(.*)/) {
                 $write_configs = 1;
         } else {
            printf STDOUT "\nHS2 BUMMER: Like unrecognized command line option or something: \"%s\", whatever! \n\n", $_;
            print STDOUT $usage_message;
            exit;
         }
      }
}
