#!/bin/bash

export VASY=vasy
export FLATBEH=flatbeh
export BOOM=boom
export BOOG=boog
export LOON=loon
export ASIMUT=asimut
export LVX=lvx
export X2Y=x2y
export FLATLO=flatlo
export CRIT_PATH=find_crit_path
export BOOG_CHECK=boog_check
export LOON_CHECK=loon_check

export MBK_TARGET_LIB=/usr/share/pharosc/alliance/cells/sxlib100
export RDS_TECHNO_NAME=/usr/share/pharosc/etc/cmos.rds
export MBK_SPI_MODEL=/usr/share/pharosc/etc/spimodel.cfg
export DREAL_TECHNO_NAME=/usr/share/pharosc/etc/cmos.dreal
export GRAAL_TECHNO_NAME=/usr/share/pharosc/etc/cmos.graal

export MBK_WORK_LIB=.
export MBK_IN_LO=vst
export MBK_OUT_LO=vst
export MBK_CATA_LIB=.:$MBK_TARGET_LIB
CATAL_NAME=SXLIB100

cp $MBK_TARGET_LIB/$CATAL_NAME .
export MBK_CATAL_NAME=$CATAL_NAME

track_pitch=5
row_height=50

max_boom_netlists=1000
boog_timeout=3
loon_timeout=10
short_sleep=0.5

kill_loon ()
{
  kill_loop=0
  while [ "$(ps -a | grep ' loon$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ')" != "" ]
  do
    kill -9 $(ps -a | grep ' loon$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ') 2>/dev/null
    if [ "$kill_loop" -gt 10 ]
    then
      break
    fi
    let "kill_loop=kill_loop+1"
  done
}
kill_boog_check ()
{
  if [ "$(ps -a | grep ' boog_check$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ')" != "" ]
  then
    kill -9 $(ps -a | grep ' boog_check$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ') 2>/dev/null
  fi
}
kill_loon_check ()
{
  if [ "$(ps -a | grep ' loon_check$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ')" != "" ]
  then
    kill -9 $(ps -a | grep ' loon_check$' | tail -1 | sed 's/^ *//' | tr -s ' ' ' ' | cut -f1 -d' ') 2>/dev/null
  fi
}
get_path_delay ()
{
  path_delay=$(cat $$loon_out | \
    grep 'Critical' | cut -f4 -d' ' | tr -s '.' '.' | cut -f2 -d'.')
  cell_gates=$(echo $[($(grep 'Area on file' $$loon_out | \
    sed -n '2 p' | cut -f4 -d' ' | tr -s . | cut -f3 -d'.') \
    +$track_pitch*$row_heig/usr/share/pharosc/$track_pitch/$row_height])
  case $path_delay in
  [0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])
# complicated way to ignore path_delay unless it is positive integer less than 100000
    ;;
  *)
    continue
    ;;
  esac
}
check_or_continue ()
{
  if test ! -f "$1"
  then # ignore this loon if no xsc output file
    rm -f $$loon_out
    continue
  fi
  if test ! -f $$loon_out
  then # check it before using it to make sure
    continue
  fi
}

# CREATE NETLISTS ACCORDING TO DOC BY PALACIOS
$BOOM -l 3 -d 0 myppg4 ppg4 | egrep 'BOOl|Parse|Drive'
$BOOG -x 0 -m 4 ppg4 myppg4 2>/dev/null | egrep 'Binding|^Mapping file|^Saving file'
$LOON -x 0 -m 4 myppg4 ppg4 | egrep 'Local optimization|^Area on file|^Critical path'

$BOOM -l 3 -d 0 myha ha | egrep 'BOOl|Parse|Drive'
$BOOG -x 0 -m 4 ha myha 2>/dev/null | egrep 'Binding|^Mapping file|^Saving file'
$LOON -x 0 -m 4 myha ha | egrep 'Local optimization|^Area on file|^Critical path'

$BOOM -l 3 -d 0 myfa fa | egrep 'BOOl|Parse|Drive'
$BOOG -x 0 -m 4 fa myfa 2>/dev/null | egrep 'Binding|^Mapping file|^Saving file'
$LOON -x 0 -m 4 myfa fa | egrep 'Local optimization|^Area on file|^Critical path'

$FLATBEH mywallace mywallace | egrep 'abstractor|Netlist file|Output  file'
$BOOM -l 3 -d 0 mywallace wallace | egrep 'BOOl|Parse|Drive'
$BOOG -x 0 -m 4 wallace swallace 2>/dev/null | egrep 'Binding|^Mapping file|^Saving file'
$LOON -x 0 -m 4 swallace wallace | egrep 'Local optimization|^Area on file|^Critical path'

flatbeh myadd5 myadd5 | egrep 'abstractor|Netlist file|Output  file'
$BOOM -l 3 -d 0 myadd5 add5 | egrep 'BOOl|Parse|Drive'
$BOOG -x 0 -m 4 add5 sadd5 2>/dev/null | egrep 'Binding|^Mapping file|^Saving file'
$LOON -x 0 -m 4 sadd5 add5 | egrep 'Local optimization|^Area on file|^Critical path'

# LOOP THE SYNTHESIS STEPS FROM PALACIOS TO GET FASTEST NETLIST
# ONE FLATBEH, THEN BOOM LOOP THEN BOOG AND LOON LOOP WITH OPT_LEVEL=4
$FLATBEH mymulti4 mymulti4 | egrep 'abstractor|Netlist file|Output  file'

##### BOOM LOOP #####
boom_netlists=0; tot_netlists=0
while [ "$tot_netlists" -lt "$max_boom_netlists" ]
do
  for boom_opt in 1 2 3 4
  do
    for delay in 100 75 50 25 0
    do
      case $boom_opt in
      1)
        nice -10 $BOOM -l 3 -d $delay -AO mymulti4 multi4 >/dev/null
        ;;
      2)
        nice -10 $BOOM -l 3 -d $delay -A mymulti4 multi4 >/dev/null
        ;;
      3)
        nice -10 $BOOM -l 3 -d $delay -O mymulti4 multi4 >/dev/null
        ;;
      4)
        nice -10 $BOOM -l 3 -d $delay mymulti4 multi4 >/dev/null
        ;;
      esac
      egrep -v '^--|^ *$' multi4.vbe > multi4_${boom_netlists}.vbe
      prev_loop=0; netlist_exists=0
      while [ "$prev_loop" -lt "$boom_netlists" ]
      do
        if [ "$(diff -biq multi4_${prev_loop}.vbe multi4_${boom_netlists}.vbe)" = "" ]
        then
          netlist_exists=1
          break
        fi
        let "prev_loop=prev_loop+1"
      done
      if [ "$netlist_exists" -eq 1 ]
      then
        let "tot_netlists=tot_netlists+1"
        continue
      else
        if [ "$[$boom_netlists%10]" -eq 0 ]
        then echo "# Netlist "$multi4_${boom_netlists}" from "$tot_netlists
        fi
        let "boom_netlists=boom_netlists+1"
      fi
      let "tot_netlists=tot_netlists+1"
    done
  done
done
echo "# "$boom_netlists" BOOM netlists"

##### BOOG AND LOON LOOP #####
syn_loop=-1
min_path_delay=9999
while [ "$syn_loop" -le "$boom_netlists" ]
do
  let "syn_loop=syn_loop+1"
  rm -f smulti4.xsc
  nice -10 $BOOG_CHECK smulti4.xsc $short_sleep $boog_timeout &
  nice -10 $BOOG -m 4 multi4_${syn_loop} smulti4 2>/dev/null >/dev/null
  kill_boog_check
  if test -f smulti4.xsc
  then
    rm -f multi4_tmp.xsc
    nice -10 $LOON_CHECK multi4_tmp.xsc $short_sleep $loon_timeout &
    nice -10 $LOON -x 0 -m 4 smulti4 multi4_tmp 2>/dev/null > $$loon_out
    kill_loon_check
    check_or_continue multi4_tmp.xsc
    rm -f multi4.xsc
    nice -10 $LOON_CHECK multi4.xsc $short_sleep $loon_timeout &
    nice -10 $LOON -x 0 -m 0 multi4_tmp multi4 2>/dev/null > $$loon_out
    kill_loon_check
    check_or_continue multi4.xsc

    update=0
    get_path_delay # gets $path_delay and $cell_gates
    if [ "$min_path_delay" = "" ]
    then
#   Use this path_delay
      min_path_delay=$path_delay
      min_cell_gates=$cell_gates
      update=1
    elif [ "$path_delay" -lt "$min_path_delay" ]
#   This path delay is the fastest to this stage so far
    then
      min_path_delay=$path_delay
      min_cell_gates=$cell_gates
      update=1
    elif [ "$path_delay" -eq "$min_path_delay" -a "$cell_gates" -lt "$min_cell_gates" ]
    then
#   Same delay as before but with fewer gates
      min_cell_gates=$cell_gates
      update=1
    fi
    if [ "$update" -eq 1 ]
    then
      cp -p multi4_${syn_loop}.vbe multi4_a.vbe 2>/dev/null
      cp -p multi4.vst multi4_a.vst 2>/dev/null
      cp -p multi4.xsc multi4_a.xsc 2>/dev/null
      cp -p $$loon_out multi4_a.loonout
      echo "# Netlist "$syn_loop", Critical path ..."$min_path_delay" ps, Area ..."$min_cell_gates" tracks"
    fi

    if [ "$[$syn_loop%10]" -eq 0 ]
    then echo "# Netlist "$syn_loop", "$path_delay
    fi
  fi
done
rm -f multi4_[0-9]*.vbe multi4.vst multi4_tmp.*

# LOOP LOON AROUND THE USER ENTERED NETLISTS
cp myppg4.vst ppg4.vst
cp mywallace.vst wallace.vst
cp myadd5.vst add5.vst

syn_loop=0
min_path_delay=9999
for loon_loop1 in 0 1 2 4
do
  rm -f smulti4.xsc
  nice -10 $LOON_CHECK smulti4.xsc $short_sleep $loon_timeout &
  nice -10 $LOON -x 0 -m $loon_loop1 mymulti4 smulti4 > $$loon_out
  kill_loon_check
  if test -f smulti4.xsc
  then
    for loon_loop2 in 0 1 2 4
    do
      rm -f multi4_tmp.xsc
      nice -10 $LOON_CHECK multi4_tmp.xsc $short_sleep $loon_timeout &
      nice -10 $LOON -x 0 -m $loon_loop2 smulti4 multi4_tmp > $$loon_out
      kill_loon_check
      check_or_continue multi4_tmp.xsc
      rm -f multi4.xsc
      nice -10 $LOON_CHECK multi4.xsc $short_sleep $loon_timeout &
      nice -10 $LOON -x 0 -m 0 multi4_tmp multi4 > $$loon_out
      kill_loon_check

      if test -f multi4.xsc
      then
        update=0
        get_path_delay # gets $path_delay and $cell_gates
        if [ "$min_path_delay" = "" ]
        then
#       Use this path_delay
          min_path_delay=$path_delay
          min_cell_gates=$cell_gates
          update=1
        elif [ "$path_delay" -lt "$min_path_delay" ]
#       This path delay is the fastest to this stage so far
        then
          min_path_delay=$path_delay
          min_cell_gates=$cell_gates
          update=1
        elif [ "$path_delay" -eq "$min_path_delay" -a "$cell_gates" -lt "$min_cell_gates" ]
        then
#       Same delay as before but with fewer gates
          min_cell_gates=$cell_gates
          update=1
        fi
        if [ "$update" -eq 1 ]
        then
          cp -p multi4.vst multi4_b.vst 2>/dev/null
          cp -p multi4.xsc multi4_b.xsc 2>/dev/null
          cp -p $$loon_out multi4_b.loonout
          echo "# Netlist "$syn_loop", Critical path ..."$min_path_delay" ps, Area ..."$min_cell_gates" tracks, sequence="${loon_loop1}${loon_loop2}
        fi
      fi
      let "syn_loop=syn_loop+1"
    done
  else
    let "syn_loop=syn_loop+1"
  fi
done
rm -f multi4.vst multi4.xsc $$loon_out multi4_tmp.*

# CRITICAL PATHS
$CRIT_PATH multi4_a
$CRIT_PATH multi4_b

# SIMULATION CHECKS
$ASIMUT -b multi4_a ../multi4 res_beh_a >/dev/null
$ASIMUT    multi4_a ../multi4 res_log_a >/dev/null
$ASIMUT    multi4_b ../multi4 res_log_b >/dev/null
