#!/bin/tcsh -f
#
# synth_script.sh:
#-------------------------------------------------------------------------
#
# This script synthesizes verilog files.
#
#-------------------------------------------------------------------------
# November 2006
# Steve Beccue and Tim Edwards
# MultiGiG, Inc.
# Scotts Valley, CA
#-------------------------------------------------------------------------

if ($#argv < 2) then
   echo Usage:  synth_script.sh <technology> [options] <vname>
   exit 1
endif

set techname=${argv[1]:al}
set argline=`getopt "c:b:f:nx" $argv[2-]`

# Corrected 9/9/08; quotes must be added or "-n" disappears with "echo".
set options=`echo "$argline" | awk 'BEGIN {FS = "-- "} END {print $1}'`
set cmdargs=`echo "$argline" | awk 'BEGIN {FS = "-- "} END {print $2}'`
set argc=`echo $cmdargs | wc -w`

rm -f synth.log >& /dev/null
touch synth.log

#---------------------------------------------------------------------
# check host and number of arguments. . .
#---------------------------------------------------------------------

if ("${techname}" == "osu035") then
   set flopcell=DFFPOSX1
   set flopset=DFFSR
   set setpin=S
   set flopreset=DFFSR
   set resetpin=R
   set bufcell=BUFX2
   set inverter=INVX1
   set srflop=DFFSR
   set orgate=OR2X1
   set andgate=AND2X1
   set techfile=SCN4M_SUBM.20
   set leffile=osu035_stdcells.lef
else if ("${techname}" == "xh035") then
   set flopcell=DFRQX1
   set flopset=DFRSQX1
   set setpin=SN
   set flopreset=DFRRQX1
   set resetpin=RN
   set bufcell=BUX1
   set inverter=INX1
   set srflop=DFRRSQX1
   set orgate=OR2X1
   set andgate=AND2X1
   set techfile=xh035
   set leffile=D_CELLS.lef
else
   echo "Don't know about technology '${techname}'.  Use OSU035 or XH035"
   exit 1
endif

if ($argc == 2) then
   set argv1=`echo $cmdargs | cut -d' ' -f1`
   set argv2=`echo $cmdargs | cut -d' ' -f2`
else if ($argc == 1) then
   if (!( -f /usr/local/bin/vis )) then
      echo "No executable /usr/local/bin/vis"
      exit 1
   endif
   set argv1=`echo $cmdargs`
   set argv2=""
else
   echo Usage:  synth_script.sh <technology> [options] <vname> [<lname>]
   echo   where
   echo	      <technology> is "OSU035" or "XH035"
   echo	      <vname> is the root name of the verilog file (including path), and
   echo	      [<lname>] is the root name of the layout (.mag) file (no path).
   echo	      [options] are passed verbatim to the AddIOToBDNet program.
   exit 1
endif

set rootname=${argv1:t:r}
set srcdir=${argv1:h}

#---------------------------------------------------------------------------
# Find the file.  We assume a directory structure in which the source file
# is either in the current working directory or some searchable subdirectory
# of it.  We create subdirectory "synthesis" where we will put all output
# files from the synthesis part of the flow.
#---------------------------------------------------------------------------

set curdir=`pwd`
set fullpath=`find . -name ${rootname}.v -print`
set found=`echo $fullpath | wc -w`

#---------------------------------------------------------------------
# If we find multiple source files of the same name, and we have been
# given a full path to one of them, then use it.  Otherwise,  use the
# first one found.
#---------------------------------------------------------------------

if ($found > 1) then
   set sf=0
   foreach f ($fullpath)
      if ("${f:h}" == "./$srcdir") then
         set srcdir=${f:h}
	 set sf=1
	 break
      endif
   end
   if ($sf == 0) then
      set srcdir=${fullpath[1]:h}
      echo "Warning:  Multiple paths to source file.  Using $srcdir"
   endif
   set topdir=${srcdir:h}
else if ($found == 1) then
   set srcdir=${fullpath:h}
   set topdir=${srcdir:h}
else 
   if ($srcdir == ${argv1:t}) then
      set srcdir="."
      set topdir="."
   else
      set topdir=${srcdir:h}
   endif
endif

# Find the path to all our scripts and libraries

if ( -d ${curdir}/scripts ) then
   set scriptdir=${curdir}/scripts
else
   if ( -d ${topdir}/scripts ) then
      set scriptdir=${topdir}/scripts
   else
      set scriptdir=${curdir}
   endif
endif

if ( -d ${curdir}/lib ) then
   set libdir=${curdir}/lib
else
   if ( -d ${topdir}/lib ) then
      set libdir=${topdir}/lib
   else
      set libdir=${curdir}
   endif
endif

# Preprocessor removes "initial" blocks from the verilog
# source and saves the initial states in a ".init" file
# for post-processing

${scriptdir}/preproc.tcl ${srcdir}/${rootname}.v

vis >>& synth.log << EOF
read_verilog ${srcdir}/${rootname}_tmp.v
write_blif ${srcdir}/${rootname}.blif
quit
EOF

#---------------------------------------------------------------------
# Check for verilog compile-time errors
#---------------------------------------------------------------------

set errline=`cat synth.log | grep "No file has been read in" | wc -l`
if ( $errline == 1 ) then
   echo ""
   echo "Verilog compile errors occurred:"
   echo "See file synth.log for details."
   echo "----------------------------------"
   cat synth.log | grep "^line"
   echo ""
   exit 1
endif

sis >> synth.log << EOF
read_blif ${srcdir}/${rootname}.blif
rlib ${libdir}/${techname:au}.genlib

sweep; eliminate -1
simplify -m nocomp
eliminate -1

sweep; eliminate 5
simplify -m nocomp
resub -a

fx
resub -a; sweep

eliminate -1; sweep
full_simplify -m nocomp

map -n 0 -s
write_bdnet ${srcdir}/${rootname}.bdnet
quit
EOF

echo ""
echo "Please check ${srcdir}/${rootname}.bdnet with a text editor."
echo "Right column numbers must be unique."
echo ""

set synthdir=${topdir}/synthesis
mkdir -p ${synthdir}

#---------------------------------------------------------------------
# Check whether any clocks are used before automatically inserting one...
#---------------------------------------------------------------------

set clkpins=`cat ${srcdir}/${rootname}.bdnet | grep -c UNCONNECTED`

if ( "$clkpins" > 0 ) then

    # force spaces inside the parentheses, then count by field to get clock name
    set clkname=`cat ${srcdir}/${rootname}.v | grep always | grep posedge |\
	sed -e '/)/s/)/ )/' -e '/(/s/(/( /' -e '/ /s/  / /g' | cut -d' ' -f 4`

    cat ${srcdir}/${rootname}.bdnet |\
	sed -e /UNCONNECTED/s/UNCONNECTED/\"$clkname\"/ |\
	sed -e '/^INPUT/a\\
	"@@" : "@@"' |\
	sed -e /@@/s/@@/$clkname/g > ${synthdir}/${rootname}.bdnet
else
    cp ${srcdir}/${rootname}.bdnet ${synthdir}/${rootname}.bdnet
endif

CleanUpBdnet -f -b ${synthdir}/${rootname}.bdnet > \
	${synthdir}/${rootname}_tmp.bdnet

#---------------------------------------------------------------------
# Add initial conditions with set and reset flops
#---------------------------------------------------------------------

${scriptdir}/postproc.tcl ${synthdir}/${rootname}_tmp.bdnet \
	${srcdir}/${rootname}.init \
	$flopcell $flopset $setpin $flopreset $resetpin \
	$srflop $inverter $orgate $andgate

AddIO2BDnet -t ${libdir}/${techname:au}.genlib \
	-b ${bufcell} -f ${flopcell} $options \
	${synthdir}/${rootname}_tmp.bdnet \
	> ${synthdir}/${rootname}_buf.bdnet

#---------------------------------------------------------------------
# Check all gates for fanout load, and adjust gate strengths as
# necessary.  Iterate this step until all gates satisfy drive
# requirements.
#
# Use option "-o value" to force a value for the (maximum expected)
# output load, in fF.  Currently, there is no way to do this from the
# command line (default is 18fF). . .
#---------------------------------------------------------------------

if ( ${argv2} == "noopt" ) then

   echo "(No gate size optimization)" >> synth.log

else

   echo "" >> synth.log
   if (-f ${libdir}/gate.cfg && -f `which BDnetFanout` ) then
      set nchanged=1000
      while ($nchanged > 0)
         mv ${synthdir}/${rootname}_buf.bdnet ${synthdir}/tmp.bdnet
         BDnetFanout -l 75 -o 25 -p ${libdir}/gate.cfg ${synthdir}/tmp.bdnet \
		${synthdir}/${rootname}_buf.bdnet >>& synth.log
         set nchanged=$status
         echo "nchanged=$nchanged"
      end
   endif

endif

echo ""
echo "Generating RTL verilog and SPICE netlist file in directory ${synthdir}"
echo "Files:"
echo "   Verilog: ${synthdir}/${rootname}.rtl.v"
echo "   Verilog: ${synthdir}/${rootname}.rtlnopwr.v"
echo "   SPICE:   ${synthdir}/${rootname}.net"
echo "   SPICE:   ${synthdir}/${rootname}.spi"
echo ""

echo "Running Bdnet2Verilog."
Bdnet2Verilog ${synthdir}/${rootname}_buf.bdnet \
 	> ${synthdir}/${rootname}.rtl.v

# cat ${synthdir}/${rootname}.rtl.v | \
# 	sed -e '/input VSS/s/input VSS, VDD; //' \
# 	    -e '/( VSS/s/( VSS, VDD, /( /' \
# 	    -e '/.VSS/s/.VSS(VSS), .VDD(VDD),/ /' \
# 	> ${synthdir}/${rootname}.rtlnopwr.v

cat ${synthdir}/${rootname}.rtl.v | \
	sed -e '/.VSS/s/.VSS(VSS), .VDD(VDD),/ /' \
	> ${synthdir}/${rootname}.rtlnopwr.v

# echo "Running Bdnet2BSpice."
# Bdnet2BSpice ${synthdir}/${rootname}_buf.bdnet \
# 	> ${synthdir}/${rootname}.net

# cat ${synthdir}/${rootname}.net | sed s/"vdd vss "/"  "/ \
#	> ${synthdir}/${rootname}.spi

cd ${curdir}

#-------------------------------------------------------------------------
# Clean up after myself!
#-------------------------------------------------------------------------

rm -f ${rootname}.enc >& /dev/null
rm -f /tmp/vis.* >& /dev/null
rm -f ${synthdir}/${rootname}_tmp.bdnet >& /dev/null
rm -f ${synthdir}/${rootname}_tmp_tmp.bdnet >& /dev/null
rm -f ${synthdir}/tmp.bdnet >& /dev/null
rm -f ${srcdir}/${rootname}.bdnet
rm -f ${srcdir}/${rootname}_tmp.v
rm -f ${srcdir}/${rootname}.init
rm -f ${srcdir}/${rootname}.blif
rm -f ${curdir}/*.enc

#-------------------------------------------------------------------------
# Create the .cel file for TimberWolf
#-------------------------------------------------------------------------

set layoutdir=${topdir}/layout
mkdir -p ${layoutdir}

echo "Running bdnet2cel.tcl"
${scriptdir}/bdnet2cel.tcl ${synthdir}/${rootname}_buf.bdnet \
	${libdir}/${leffile} \
	${layoutdir}/${rootname}_buf.cel

# Don't overwrite an existing .par file.
if (!(-f ${layoutdir}/${rootname}_buf.par)) then
   cp ${libdir}/${techname:al}.par ${layoutdir}/${rootname}_buf.par
endif

echo "Edit ${layoutdir}/${rootname}_buf.par, then run place_and_route.sh"

