# create_project.tcl — 自动创建 Vivado 工程（仿真用），加载 ML-KEM KeyGen
# 顶层 mlkem_top 及其全部叶子算子与参数化 KAT testbench。
#
# 与已验证的 XSIM 流程（sync_rtl/top/TB/xsim_run.tcl）保持一致：
#   - 仅加载 mlkem_top 实际依赖的 14 个源文件
#   - 顶层仿真模块 = tb_mlkem_kg_katK_xsim
#   - 运行时安全等级由 generic KP（2/3/4）选择，用例号由 +CASE 选择
#
# Usage:
#   cd ~/Dev/mlkem
#   vivado -mode batch -source create_project.tcl
# 或在 Vivado Tcl Console 中：
#   source create_project.tcl
#
# 切换被仿真的配置（默认 KP=2, CASE=0）：编辑下方 SIM_KP / SIM_CASE 后重跑，
# 或在工程打开后执行：
#   set_property generic "KP=4" [get_filesets sim_1]
#   set_property -name {xsim.simulate.xsim.more_options} -value {-testplusarg CASE=2} -objects [get_filesets sim_1]

set PROJECT_NAME  mlkem
set PROJECT_DIR   [file normalize [file dirname [info script]]]

# 默认仿真配置（可改）
set SIM_KP    2     ;# ML-KEM 方案：2=512, 3=768, 4=1024
set SIM_CASE  0     ;# KAT 用例号（K=2: 0..4, K=3/4: 0..2）

# 仅仿真工程，无需指定 FPGA part（XSim 用默认 part 即可）
create_project -force ${PROJECT_NAME} ${PROJECT_DIR}/vivado_prj

set_property target_simulator XSim [current_project]

# ===================================================================
# RTL 源文件 —— 与 xsim_run.tcl 完全一致的 14 个文件
# ===================================================================

# ── SHA3 / Keccak ──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/sha3/keccak_round.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/sha3/keccak_core.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/sha3/sha3_top_shared.v

# ── 采样（共享 keccak_core 变体）──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/sample_ntt/sample_ntt_sync_shared.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/sample_cbd/sample_cbd_sync_shared.v

# ── NTT ──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/ntt/barrett_mul.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/ntt/zeta_rom.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/ntt/butterfly_unit.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/ntt/ntt_core.v

# ── 多项式乘法 ──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/poly_mul/basecase_mul.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/poly_mul/poly_mul_zeta_rom.v
read_verilog -sv ${PROJECT_DIR}/sync_rtl/poly_mul/poly_mul_sync.v

# ── 顶层 KeyGen 集成 ──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/top/mlkem_top.v

# ── 参数化 KAT testbench ──
read_verilog -sv ${PROJECT_DIR}/sync_rtl/top/TB/tb_mlkem_kg_katK_xsim.v

# ===================================================================
# 仿真设置
# ===================================================================

# 顶层仿真模块
set_property top tb_mlkem_kg_katK_xsim [get_filesets sim_1]
set_property top_lib xil_defaultlib [get_filesets sim_1]

# `include "sync_rtl/common/defines.vh" 的包含路径（相对工程根）
set_property include_dirs ${PROJECT_DIR} [get_filesets sim_1]

# 运行时安全等级：通过 TB 顶层 generic KP 传入（2/3/4）
set_property generic "KP=${SIM_KP}" [get_filesets sim_1]

# 跑到 $finish 为止；显式时标（XSim 默认已加 --relax，勿重复）
set_property -name {xsim.simulate.runtime} -value {all} -objects [get_filesets sim_1]
set_property -name {xsim.elaborate.xelab.more_options} \
  -value {--timescale 1ns/1ps} -objects [get_filesets sim_1]

# ===================================================================
# 测试向量：Vivado GUI 在 vivado_prj/mlkem.sim/sim_1/behav/xsim/ 下运行
# xsim，而 TB 的 $readmemh 路径相对工程根（sync_rtl/top/TB/vectors/…）。
# 用 compile 的 pre-hook（在 xsim 工作目录、且在 compile/elaborate/simulate
# 之前执行）把整套 KAT 向量复制到同名相对路径下；CASE 经 -testplusarg 选择。
#
# 注意：2019.2 的 sim_1 没有 simulate.tcl.pre 属性，且追加 -tclbatch 会排在
# Vivado 自带（含 "run all"）的 tclbatch 之后、即仿真跑完才执行（太迟）。
# 因此用 xsim.compile.tcl.pre —— 它最早执行且就在仿真工作目录里。
# ===================================================================
set pre_tcl [file join ${PROJECT_DIR} vivado_prj copy_vectors_pre.tcl]
set fp [open $pre_tcl w]
puts $fp "# Auto-generated by create_project.tcl: 复制 KAT 向量到 xsim 工作目录"
puts $fp "file mkdir sync_rtl/top/TB/vectors"
puts $fp "foreach v \[glob -nocomplain [file join ${PROJECT_DIR} sync_rtl top TB vectors kat_k*_c*_*.hex]\] {"
puts $fp "    file copy -force \$v sync_rtl/top/TB/vectors/"
puts $fp "}"
puts $fp "puts {\[create_project\] KAT vectors copied to xsim working dir}"
close $fp

set_property -name {xsim.compile.tcl.pre} -value $pre_tcl -objects [get_filesets sim_1]
set_property -name {xsim.simulate.xsim.more_options} \
  -value "-testplusarg CASE=${SIM_CASE}" \
  -objects [get_filesets sim_1]

# ===================================================================
puts "========================================"
puts " Project created: ${PROJECT_DIR}/vivado_prj/${PROJECT_NAME}.xpr"
puts " 仿真配置: ML-KEM K=${SIM_KP}, KAT CASE=${SIM_CASE}"
puts " 运行仿真:  launch_simulation; run all"
puts " 期望输出:  K=${SIM_KP} CASE ${SIM_CASE} PASS: ek==pk, dk==sk"
puts ""
puts " 切换配置（如 K=4）：编辑脚本顶部 SIM_KP/SIM_CASE 重跑本脚本，"
puts " 或在已打开工程中改 generic 后 relaunch_sim。"
puts "========================================"
