# =============================================================================
# synth_pass1.tcl — Pass 1: Area-Balanced Synthesis
# =============================================================================
# Synthesizes design from RTL using an area-focused ABC strategy.
# The resulting netlist is analyzed by STA, and if timing is violated,
# Pass 2 performs targeted timing recovery on this netlist.
#
# This is the opencos-adapted version of timing_flow/tcl/synth_pass1.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
#     DELAY_TARGET_PS   — ABC delay target in picoseconds
#     FILE_SUFFIX       — Suffix for output file naming
#
#   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}_pass1.syn.v   — 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 delay_ps      $::env(DELAY_TARGET_PS)
set file_suffix   $::env(FILE_SUFFIX)

puts "========================================================"
puts "PASS 1: AREA-BALANCED SYNTHESIS"
puts "========================================================"
puts "Top Module:     $top_module"
puts "Delay Target:   $delay_ps ps"
puts "File Suffix:    $file_suffix"
puts "========================================================"

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

# Support multiple input methods (same as syn_basic.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 (preserves major hierarchy, flattens leaf cells) ---
flatten -wb

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

# --- Resource Sharing ---
share

# --- Main Synthesis (without ABC — we call ABC separately) ---
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: Area-Focused (&nf -a) ---
# Uses the &nf mapper with SAT-based area optimization.
# This produces the smallest area but may leave timing violations,
# which Pass 2 will recover.
puts ""
puts "INFO: ABC area-focused mapping (&nf -a)..."
abc -liberty $liberty_abc \
    -script "+strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf -a; &put"

opt
opt_clean

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

# --- Statistics ---
puts ""
puts "========================================================"
puts "PASS 1 SYNTHESIS STATISTICS"
puts "========================================================"
stat -liberty $liberty_abc

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

puts ""
puts "Pass 1 netlist: $outfile"
puts "========================================================"
