# -*- tcl -*-

# Synthesis Script for Cadence Genus for use in LSU EE 4755 Homework 5

set verilog_source hw05-sol.v

# Possible effort levels: none, low, medium, high
#
set syn_level "high"
set_db syn_global_effort $syn_level
#
# See the Genus Attribute Reference

# Output files written by this script.
#
set spew_file "spew.log"
set report_file "syn-report.log"
set rpt_chan [open $report_file w]


puts "Synthesizing at effort level \"$syn_level\"\n"
puts $rpt_chan "Synthesizing at effort level \"$syn_level\"\n"


# Main Synthesis Routine
#
proc syn_mod {modname delay_target par } {

    set wall_start_ms [clock microseconds]

    global verilog_source spew_file report_file mods_comb rpt_chan

    # Load the Verilog file into Genus
    #
    read_hdl $verilog_source

    set elab_cmd "elaborate $modname -parameters { $par } "

    puts $rpt_chan "\n** Elaborating $modname with delay target $delay_target \n   Using command $elab_cmd"

    # Elaborate the chosen module, and make sure that any error message
    # is printed on stdout.
    #
    if { [catch {redirect -msg -variable elab_spew $elab_cmd} design_name ] } {
        puts "Errors encountered while elaborating using"
        puts "   \"$elab_cmd\"\n$elab_spew\n"
        exit 1
    }

    # Write output of the elaboration command.
    #
    redirect -append $spew_file {puts $elab_spew}

    vcd $design_name
    set mod_dir_name [vbasename $design_name]

    # Set delay constraints.
    #
    set is_comb [ expr { $modname in $mods_comb } ]
    if [ expr { $is_comb } ] {
        create_clock -name clk -period $delay_target
        set_input_delay -clock clk 0.0 [all_inputs]
        set_output_delay -clock clk 0.0 [all_outputs]
    } else {
        create_clock -name clk -period $delay_target [clock_ports]
        set_input_delay -clock clk 0.0 [all_inputs -no_clocks]
        set_output_delay -clock clk 0.0 [all_outputs]
    }

    # Perform the three synthesis steps.
    #
    redirect -append $spew_file "syn_gen"
    redirect -append $spew_file "syn_map"
    redirect -append $spew_file "syn_opt"

    # Stop timer, used for showing how long synthesis took.
    #
    set wall_stop_ms [clock microseconds]

    # Get an area report, and write it to a file.
    #
    redirect -variable sm_area_report "report area -summary"
    puts $rpt_chan $sm_area_report

    # Scrape the synthesized module area from the output of the report
    # command.
    #
    foreach line [split $sm_area_report "\n"] {
        if { [ regexp -all "^$modname" $line ] } {
            regexp {([.0-9]+)\s*$} $line whole area
        } }

    # Get a timing report, and write it to a file.
    #
    redirect -variable sm_timing_report "report timing"
    puts $rpt_chan $sm_timing_report

    # Scrape the synthesized module critical path delay from the
    # report.
    set lines [split $sm_timing_report "\n"]
    foreach line $lines {
        if { [ regexp -all {\m(Data Path)} $line ] } {
            regexp {([0-9.]+)} $line whole delay
        }
    }

    # Write a row of the synthesis results table.
    #
    puts [format "%-32s   %7.0f  %6.3f  %6.1f ns  %5.0f s" \
              $mod_dir_name $area [ expr { $delay / 1000.0 } ] $delay_target \
          [ expr { ( $wall_stop_ms - $wall_start_ms ) * .000001 } ] ]
}


# Write the heading of the synthesis results table.
#
puts [format "%-32s   %7s  %6s  %6s     %5s" "Module Name" "Area" "Delay"  "Delay" "Synth"  ]
puts [format "%-32s   %7s  %6s  %6s     %5s" ""             ""    "Actual" "Target" "Time" ]


# List of combinational modules.
#
set mods_comb { ms_comb m1_comb try_mult try_add try_sq m1_a3 m1_mad m1_mm m1_comb_v3 m1_comb_sos m1_comb_sop m1_comb_ssp m1_comb_alt }
#
# It is important to add combinational modules to this list.


# Lists of modules to synthesize. Note that only the last
# assignment to mods has an effect.
#
set mods { m1_comb m1_seq m1_pipe }
set mods { try_mult try_add try_sq }
set mods { ms_comb ms_seq ms_pipe }
set mods { m1_comb_alt }

# Delay constraints.
#
set delay_targets { 100 }

# Significand lengths
#
set wsigs { 7 23 }


# For those who don't want to use a loop, uncomment the lines below.
#
# syn_mod try_mult 5 "7 8 0"
# syn_mod try_mult 5 "7 6 0"
#
# close $rpt_chan
# quit

# Synthesize the modules in mods, with the significand lengths
# in wsigs, for the delay targets in delay_targets.
#
foreach delay_target $delay_targets {
    foreach ws $wsigs {
        foreach mod $mods {
            syn_mod $mod $delay_target " $ws 8 0 "
        }
    }
}



close $rpt_chan
quit