# Note: this complete ESNUG has been fully commented so the Perl script
# in it is ready to use! Just add water! - John Cooley, the ESNUG guy
#( ESNUG 137 Item 1 ) -------------------------------------------------- [7/93]
#
#From: uunet!uranus!splinter!flieder (Jeff Flieder)
#Subject: FSV, A Perl Script for Fixing Synopsys' Stinky Verilog Output
#
#John,
#
# I finally got around to cleaning up my FSV (Fix Synopsys Verilog) script
#so that I could send it to ESNUG users. I want to strongly state that this
#Perl script comes with no warranty and is used at the users risk. I will
#not support nor answer questions about this script, but if users want to use
#it, feel free. I will say that we are using it quite successfully here at
#Ford Microelectronics. I will try to post all major releases of FSV to you
#so that users can get timely updates.
#
# The command line to use FSV is:
#
# "FSV <list of file names>"
#
#FSV will make a copy of the original file in <file_name>.bak and will create
#a new file in place of the old one. One important note, the bang line says:
#
# "/apps/fmi/bin/perl411"
#
#This ain`t gonna work anywhere but here at Ford Microelectronics, so the
#user will have to modify this line to point to wherever their own perl
#executables are. I think that is all the information that anyone should need
#to run the script.
#
# - Jeff Flieder
# Senior Engineer, CAE Development
# Ford Microelectronics, Inc.
#!/apps/fmi/bin/perl411
#
# Purpose: FSV - a utility program for making good Verilog code
# out of "kaa-kaa" Synopsys verilog-out code.
#
# Performs the following fixes:
# 1. Finds all the busses and makes them into real busses
# 2. Removes all the escaped names
# 3. Creates busses for all multi-bit registers
#
# Written By: J.W. Flieder 3 Dec 1992
#
# Modification History:
# V 1.1: Added the capability of fixing the 'Q' outputs of
# all the registers. JWF 14-NOV-1993
# V 1.2: Changed the program so that each module is written to
# a file called module_name.v. This was done because
# the Synopsys file has the modules in the wrong order
# so that Verilog won't run correctly. JWF 15-JAN-1993
# V 1.3: Added the feature to check if a file already exists prior
# to writing a new file over the old one. JWF 25-JAN-1993
# V 1.4 Changed vectors to little endian [0:n] JWF 14-APR-1993
# V 1.5 Added the following command line options: JWF 14-APR-1993
# -h or -help : shows all command line options
# -le : specifies little endian ordering of busses
# -be : specifies big endian ordering of busses
# V 2.0 Decided enough changes have been made to make this a major
# release of the software. The following changes have been made:
# 1. Files are no longer split up since Synopsys fixed
# the problem and lower designs are written first
# 2. Displays help when there are no arguments
# JWF 4-20-93
# V 2.1 Fixed the little-endian big-endian problem and also fixed another
# net name problem by changing *cell* to cell and changing
# / to _. JWF 5-5-93
#
# V 2.2 Fixed a bug that occured if there were no single bit wires
# in a design. The software would print out a wire declaration
# with now wires in it before. Now it checks to make sure that
# there are wires before printing out the wire declaration.
$work_dir = `/bin/pwd`;
chop $work_dir;
$save_index = 0;
$not_in_wire = 1;
$wire_string = ();
$scalar_cnt = 0;
$#vectors = -1;
$endian = "";
#
# opening day niceties
#
system ("/usr/ucb/clear");
print STDOUT "\n\n";
print STDOUT "FSV: Fix Synopsys Verilog Utility Program\n\n";
print STDOUT "Version 2.1 5-MAR-1993\n\n";
if (@ARGV == 0) {
die &print_help;
}
print STDOUT "----- Processing ----\n\n";
foreach $file (@ARGV) {
print STDOUT "arg: $file \n\n";
if($file =~ /^-.*/) {
if ($file eq "-le") {
print STDOUT "Little Endian Ordering Requested ([0:n])\n\n";
$endian = "big";
}
if ($file eq "-be") {
print STDOUT "Big Endian Ordering Requested ([n:0])\n\n";
$endian = "little";
}
if (($file eq "-h") || ($file eq "-help")) {
&print_help;
}
}
else {
if($endian eq "") {
print STDOUT
"No Endian ordering specified, using Little Endian ([0:n])\n\n";
$endian = little;
}
open(INFILE, "$work_dir/$file") || die STDOUT
"Can't open $work_dir/$file for read: $!\n";
system("cp $work_dir/$file $work_dir/$file.sav");
system("rm $work_dir/$file");
open(OUTFILE, ">$work_dir/$file") || die STDOUT
"Can't open $work_dir/$file for write: $!\n";
while (<INFILE>) {
if (/endmodule/) {
&process_wires;
&process_body;
&dump_module;
&reset_arrays;
}
else {
$current_string = $current_string.$_;
#
# look for the semi-colon that terminates the current string
# replace all carraige returns with the string "PutCrHere", I
# mean what are the odds of a net having that name?
#
if(!($current_string =~ /\;$/)) {
chop($current_string);
$current_string = "$current_string.PutCrHere";
}
else {
$complete_string = $current_string;
$current_string = "";
#
# Search for the wire declaration so that all busses and wires can be
# identified and processed, and save the module declaration and the
# i/o declarations
#
#
# module declaration
#
if($complete_string =~ /\s*module\s*([^\s]*).*/) {
$module_name = $1;
print "Processing Module $module_name\n";
$file_names{$module_name} = 0;
$complete_string =~ s/.PutCrHere/g;
$module_string = $complete_string;
}
#
# inout declaration
#
elsif($complete_string =~ /^\s*inout.*/) {
$complete_string =~ s/.PutCrHere/g;
$inout_string = "$inout_string $complete_string";
}
#
# input declaration
#
elsif($complete_string =~ /^\s*input.*/) {
$complete_string =~ s/.PutCrHere/g;
$input_string = "$input_string $complete_string";
}
#
# output declaration
#
elsif($complete_string =~ /^\s*output.*/) {
$complete_string =~ s/.PutCrHere/g;
$output_string = "$output_string $complete_string";
}
#
# wire declaration string
#
elsif($complete_string =~ /^\s*wire.*/) {
$complete_string =~ /\s*([^\;]*);/; # strip leading spaces and CR
$wire_string = "$wire_string $1";
}
#
# If none of the above, we must be in the body of the Verilog module.
# The processing of the body lines consists of removing all the backslashes
# that escape all the names, renaming each arrayed instance from name[#] to
# name_# and finding all of the Q inputs to F/F's so that they can later be
# attached to busses like they should have been in the first place.
#
else {
$complete_string =~ s//g; # strip off the '\'s
$complete_string =~ s/\*cell\*/cell/g;# replace *cell* with cell
$complete_string =~ s/\_/g; # replace / with _
$_ = $complete_string;
#
# find all of the arrayed instance names and fix them by changing from
# name[#] to name_#
#
# search for instance definitions
if(/(\s+[^\s]+\s*)([^\s]*)(.*)/) {
$c_type = $1;
$i_name = $2;
$p_list = $3;
#
# find all of the Q inputs of registers and save the name for
# processing later
#
if($i_name =~ /([^\[]*)\[([^\]]*)\]/) { # parse the instance name
$i_ident = $1;
$i_num = $2;
$ext = "_Q";
$under = "_";
$new_name = "$i_ident$ext[$i_num]";
$p_list =~ /([^\.]*\.Q\()([^\)]*)(.*)/;
$old_name = $2;
$complete_string = "$c_type $i_ident$under$i_num $p_list\n";
#
# Add the new net to the wire_string array so that in can be processed later
# and add the net to the bus_name associative array so that it can be processed
# later. Only add the net if the old_name is not contained in the port list of
# the current module
#
$old_name =~ /([^\[]*).*/;
if(!($module_string =~ /)) {
$old_name =~ s//g; # remove any spaces in the name
$bus_name{$new_name} = $old_name;
$wire_string = "$wire_string, $i_ident$ext[$i_num]";
}
}
$body_array[$body_index] = $complete_string;
$body_index ++;
}
}
}
}
}
print STDOUT "\n\n<<<<< PROCESSING COMPLETED >>>>>>\n\n";
print STDOUT "\t Your original verilog netlist has been preserved\n";
print STDOUT "\t in a file called $file.sav.\n\n";
print STDOUT "\t The new netlists is called $file\n\n";
print STDOUT "\n-------------------------------------------------\n\n";
}
}
###########################################################
sub process_wires {
$wire_string = "$wire_string;";
$wire_string =~ /wire(.*;)/; # strip the word "wire"
$wire_string = $1;
$wire_string =~ s/\.PutCrHere//g; # remove the ".PutCrHere"
$wire_string =~ s//g; # remove the slashes (\)
$wire_string =~ s/\*cell\*/cell/g; # replace *cell* with cell
$wire_string =~ s/\_/g; # replace / with _
#
# search for the old net names and replace them with the new ones
#
foreach $element (sort keys(%bus_name)) {
# print "ON:$bus_name{$element}., NN:$element.\n";
$bus_name{$element} =~ /([^\[]*)\[([^\]]*)\]/;
$old_bus = $1;
$old_number = $2;
$element =~ /([^\[]*)\[([^\]]*)\]/;
$new_bus = $1;
$new_number = $2;
$wire_string =~ s/$old_bus\[$old_number\]/$new_bus\[$new_number\]/g;
}
&parse_wire_string();
&fix_wire_string();
if (@scalars != "") {
$wire_array[$wire_index] = "wire\t";
$wire_index++;
foreach $wire_name (@scalars) {
if ($start_flag == 0) {
$wire_array[$wire_index] = "\t$wire_name";
$start_flag = 1;
}
else {
$wire_array[$wire_index] = ",\n\t\t$wire_name";
}
$wire_index++;
}
$wire_array[$wire_index] = ";\n";
$wire_index++;
}
foreach $vector_name (sort keys(%vectors)) {
if ($endian eq "little") {
$wire_array[$wire_index]=
"wire[0:$vectors{$vector_name}]\t$vector_name\;\n";
}
elsif ($endian eq "big") {
$wire_array[$wire_index]=
"wire[$vectors{$vector_name}:0]\t$vector_name\;\n";
}
$wire_index ++;
}
}
############################################################
#
# subroutine: process_body
#
# purpose: this subroutine runs through each line in the body
# of the current module definition and replaces the old
# net names with new net names
#
###########################################################
sub process_body {
foreach $body_line (@body_array) {
foreach $element (sort keys(%bus_name)) {
$bus_name{$element} =~ /([^\[]*)\[([^\]]*)\]/;
$old_bus = $1;
$old_number = $2;
$element =~ /([^\[]*)\[([^\]]*)\]/;
$new_bus = $1;
$new_number = $2;
$body_line =~ s/$old_bus\[$old_number\]/$new_bus\[$new_number\]/g;
}
#
# put the carraige returns back into the strings
#
$body_line =~ s/.PutCrHere/g;
}
}
############################################################
#
# subroutine: dump_module
#
# purpose: writes out the current module arrays to the
# output file
#
#############################################################
sub dump_module {
print OUTFILE ($module_string);
print OUTFILE ($inout_string);
print OUTFILE ($input_string);
print OUTFILE ($output_string);
foreach $line (@wire_array) {
print OUTFILE $line;
}
foreach $line (@body_array) {
print OUTFILE $line;
}
print OUTFILE "endmodule\n";
}
############################################################
#
# subroutine: reset arrays
#
# purpose: resets all arrays, pointers, etc after a module dump
#
############################################################
sub reset_arrays {
$wire_index = 0;
$not_in_wire = 1;
$scalar_cnt = 0;
$body_index = 0;
$start_flag = 0;
$wire_string = "";
$module_string = "";
$inout_string = "";
$input_string = "";
$output_string = "";
@scalars = -1;
@wire_array = "";
@body_array = "";
%vectors = -1;
%bus_name = -1;
%single_names = -1;
}
############################################################
#
# subroutine: parse_wire_string
#
# purpose: parses the input wire string into individual
# wires in an array called @parsed_string
#
############################################################
sub parse_wire_string {
chop($wire_string);
@parsed_string = split(/,/,$wire_string);
# print "@parsed_string\n\n";
}
############################################################
#
# subroutine: fix_wire_string
#
# purpose: finds all the vectored and scalar nets in the wire
# string and puts them in seperate arrays
#
############################################################
sub fix_wire_string {
foreach $element (@parsed_string) {
$element =~ s//g; # remove leading spaces
if($element =~ /([^\[]*)\[(\d*)\]/) { # find all the vectored nets
# by looking for the []`s
if($vectors{$1} <= $2) {
$vectors{$1} = $2;
}
}
else {
$scalars[$scalar_cnt] = "$element";
$scalar_cnt++;
}
}
}
############################################################
#
# subroutine: print_help
#
# purpose: prints out the help string
#
############################################################
sub print_help {
print STDOUT "Command line format is:\n\n";
print STDOUT "fsv [-arg] file_name [file_name]\n\n";
print STDOUT "Arguments are: \n\n";
print STDOUT "-le : specified little endian ordering of busses [0:n]\n";
print STDOUT "-be : specified big endian ordering of busses [n:0]\n";
print STDOUT " (Note: Default is little endian)\n\n";
print STDOUT "-h or -help : displays this message\n\n";
}
|
|