# =============================================================================
# synth_pass2_full.tcl — Pass 2 Fallback: Full Re-synthesis from RTL
# =============================================================================
# If the targeted Pass 2 does not improve timing, this script re-synthesizes
# the design from RTL using the timing-aggressive ABC strategy with gate
# sizing. This is a proven approach that recovered 1.57ns WNS in testing.
#
# This is the opencos-adapted version of timing_flow/tcl/synth_pass2_full.tcl.
# It supports both filelist-based input (YOSYS_READ_SLANG_DOTF) and the
# legacy VERILOG_FILES env var.
#
# Environment Variables:
#   Required:
#     LIBERTY_FILE      — Path(s) to Liberty timing library, space-delimited
#     LIBERTY_FILE_DFF  — Single lib for dfflibmap (flip-flop mapping)
#     LIBERTY_FILE_ABC  — Single lib for abc (combinational mapping)
#     TOP_MODULE        — Top-level module name
#     OUT_DIR           — Output directory
#     FILE_SUFFIX       — Suffix for output file naming
#     DELAY_TARGET_PS   — ABC delay target in picoseconds
#     CONSTR_FILE       — Path to ABC constraints file (for gate sizing)
#
#   Input sources (at least one required):
#     YOSYS_READ_SLANG_DOTF  — Path to .f filelist (preferred)
#     YOSYS_READ_VERILOG_DOTF — Path to .f filelist (Verilog)
#     VERILOG_FILES           — Space-separated source files (legacy)
#
# Output:
#   $OUT_DIR/${TOP_MODULE}_pass2_full.syn.v   — Re-synthesized netlist
# =============================================================================

yosys -import

set liberty_files $::env(LIBERTY_FILE)
set liberty_dff   [expr {[info exists ::env(LIBERTY_FILE_DFF)] ? $::env(LIBERTY_FILE_DFF) : [lindex $liberty_files 0]}]
set liberty_abc   [expr {[info exists ::env(LIBERTY_FILE_ABC)] ? $::env(LIBERTY_FILE_ABC) : [lindex $liberty_files 0]}]
set top_module    $::env(TOP_MODULE)
set out_dir       $::env(OUT_DIR)
set file_suffix   $::env(FILE_SUFFIX)
set delay_ps      $::env(DELAY_TARGET_PS)
set constr_file   $::env(CONSTR_FILE)

puts "========================================================"
puts "PASS 2 FALLBACK: FULL RE-SYNTHESIS (TIMING-AGGRESSIVE)"
puts "========================================================"
puts "Top Module:     $top_module"
puts "Delay Target:   $delay_ps ps"
puts "Constraints:    $constr_file"
puts "========================================================"

# --- Read Inputs ---
foreach _lib $liberty_files {
    read_liberty -lib $_lib
}

# Support multiple input methods (same as synth_pass1.tcl)
if { [info exists ::env(YOSYS_READ_SLANG_DOTF)] } {
    if { [info exists ::env(TOP_MODULE)] } {
        read_slang --ignore-initial --ignore-timing --top $::env(TOP_MODULE) -f $::env(YOSYS_READ_SLANG_DOTF)
    } else {
        read_slang --ignore-initial --ignore-timing -f $::env(YOSYS_READ_SLANG_DOTF)
    }
} elseif { [info exists ::env(YOSYS_READ_VERILOG_DOTF)] } {
    read_verilog --ignore-initial --ignore-timing -f $::env(YOSYS_READ_VERILOG_DOTF)
} elseif { [info exists ::env(VERILOG_FILES)] } {
    read_slang --ignore-initial --ignore-timing --top $::env(TOP_MODULE) {*}[split $::env(VERILOG_FILES)]
} else {
    error "No input source specified: set YOSYS_READ_SLANG_DOTF, YOSYS_READ_VERILOG_DOTF, or VERILOG_FILES"
}

# --- Hierarchy & Elaboration ---
hierarchy -check -top $top_module

# --- Selective Flatten ---
flatten -wb

# --- Arithmetic Optimization ---
alumacc
opt -fast
alumacc

# --- Resource Sharing ---
share

# --- Main Synthesis (without ABC) ---
synth -top $top_module -noabc

# --- Optimization Passes ---
opt -full
opt_clean
opt_expr
opt_merge
opt -full
opt_clean -purge
opt_expr -mux_undef -mux_bool
opt_merge -share_all

# --- FSM Optimization ---
fsm
fsm_opt

# --- Memory & Flip-Flop Mapping ---
memory_dff
memory_map
dfflibmap -liberty $liberty_dff

# --- ABC Technology Mapping: Timing-Aggressive (Old Mapper + Gate Sizing) ---
puts ""
puts "INFO: ABC timing-aggressive mapping (map + upsize/dnsize)..."
abc -liberty $liberty_abc \
    -constr $constr_file \
    -script "+strash; dc2; scorr; strash; dch -f; map -D $delay_ps; buffer; upsize -D $delay_ps; dnsize -D $delay_ps; stime -p"

opt
opt_clean

# --- Final Cleanup ---
opt_clean -purge
clean
hierarchy -check

# --- Statistics ---
puts ""
puts "========================================================"
puts "PASS 2 FULL RE-SYNTHESIS STATISTICS"
puts "========================================================"
stat -liberty $liberty_abc

# --- Write Netlist ---
set outfile "$out_dir/${top_module}_pass2_full.syn.v"
write_verilog -noattr $outfile

puts ""
puts "Pass 2 (full) netlist: $outfile"
puts "========================================================"
