Files
gps/targets/fpga/vcu118/flow/vivado/scripts/build.tcl
T
2026-08-06 22:14:52 +03:00

232 lines
8.4 KiB
Tcl

set script_dir [file dirname [file normalize [info script]]]
set fpga_dir [file normalize [file join $script_dir ../../..]]
set repo_dir [file normalize [file join $fpga_dir ../../..]]
set hardware_dir [file join $repo_dir hardware]
cd $repo_dir
set part_name "xcvu9p-flga2104-2L-e"
set board_part "xilinx.com:vcu118:part0:2.4"
set top_module "vcu118_rocket_top"
set out_dir [file join $fpga_dir out]
set generated_dir [file join $out_dir build generated]
set report_dir [file join $out_dir reports]
set bit_dir [file join $out_dir bitstream]
set checkpoint_dir [file join $out_dir build checkpoints]
file mkdir $generated_dir
file mkdir $report_dir
file mkdir $bit_dir
file mkdir $checkpoint_dir
set rocket_rtl_dir [file join $hardware_dir generated vcu118-soc-verilog]
set rocket_top [file join $rocket_rtl_dir VCU118RocketSystem.sv]
set rocket_filelist [file join $rocket_rtl_dir filelist.f]
set wrapper [file join $generated_dir ${top_module}.sv]
if {[info exists ::env(GPS_SYSTEM_DIR)] && [string trim $::env(GPS_SYSTEM_DIR)] ne ""} {
set gps_system_dir [file normalize $::env(GPS_SYSTEM_DIR)]
} else {
set gps_system_dir [file join $hardware_dir external gps rtl]
}
if {[info exists ::env(RF_INPUT_MODE)]} {
set rf_input_mode [string tolower [string trim $::env(RF_INPUT_MODE)]]
} else {
set rf_input_mode "pmod"
}
if {$rf_input_mode ni {"pmod" "generated" "ethernet"}} {
error "Unsupported VCU118 RF_INPUT_MODE=$rf_input_mode. Use pmod, generated, or ethernet."
}
if {![file exists $rocket_filelist]} {
error "Rocket Verilog filelist not found: $rocket_filelist"
}
if {![file exists $rocket_top]} {
error "Rocket top Verilog not found: $rocket_top"
}
puts "Generating VCU118 wrapper: $wrapper"
puts "VCU118 RF input mode: $rf_input_mode"
exec python3 [file join $fpga_dir tools gen_vcu118_wrapper.py] \
--rocket-top $rocket_top \
--out $wrapper \
--rf-input-mode $rf_input_mode
set max_threads [string trim [exec nproc]]
puts "Using Vivado maxThreads=$max_threads"
set_param general.maxThreads $max_threads
set_part $part_name
if {[llength [get_board_parts -quiet $board_part]] != 0} {
set_property board_part $board_part [current_project]
}
proc collect_sv_files {dir} {
set files {}
foreach file [glob -nocomplain -directory $dir *.sv] {
lappend files $file
}
foreach subdir [glob -nocomplain -directory $dir -types d *] {
set files [concat $files [collect_sv_files $subdir]]
}
return $files
}
proc apply_vcu118_async_clock_groups {} {
set fabric_clk [get_clocks -quiet pll_fabric_clk]
set gps_acq_clk [get_clocks -quiet pll_gps_acq_clk]
set gps_trck_clk [get_clocks -quiet pll_gps_trck_clk]
set gps_ref_clk [get_clocks -quiet pll_gps_ref_clk]
set gps_rf_clk [get_clocks -quiet {pll_gps_rf_exact_clk pmod_rf_clk}]
set eth_clocks [get_clocks -quiet {
phy_sgmii_clk_p
IntTx_ClkOut0
IntTx_ClkOut1
IntRx_ClkOut0
riu_clk_out
rx_pll_clk_out
rx_pll_clk_out_DIV
rx_pll_clk_out_DIV_INV
rx_pll_clk_out_FIFO_WRCLK_OUT
tx_pll_clk_out
tx_pll_clk_out_DIV
}]
if {[llength $fabric_clk] == 0 ||
[llength $gps_acq_clk] == 0 ||
[llength $gps_trck_clk] == 0 ||
[llength $gps_ref_clk] == 0 ||
[llength $gps_rf_clk] == 0} {
puts "Warning: not all VCU118 base async clock groups are available yet."
return
}
set clock_group_args [list set_clock_groups -asynchronous \
-group $fabric_clk \
-group $gps_acq_clk \
-group $gps_trck_clk \
-group $gps_rf_clk]
if {[llength $eth_clocks] != 0} {
puts "Applying VCU118 async clock groups, including Ethernet PCS/PMA clocks."
lappend clock_group_args -group $eth_clocks
} else {
puts "Applying VCU118 async clock groups without Ethernet PCS/PMA clocks."
}
{*}$clock_group_args
}
proc relax_vcu118_pmod_rf_clock_route {rf_input_mode} {
if {$rf_input_mode ne "pmod"} {
return
}
set rf_clk_nets [get_nets -quiet -hierarchical -filter {NAME =~ *rf_clk_pmod_ibuf*}]
if {[llength $rf_clk_nets] == 0} {
set rf_clk_nets [get_nets -quiet -hierarchical -filter {NAME =~ *rf_clk_pmod*}]
}
if {[llength $rf_clk_nets] != 0} {
puts "Allowing non-dedicated route for low-rate VCU118 PMOD RF clock."
set_property CLOCK_DEDICATED_ROUTE FALSE $rf_clk_nets
}
}
set rocket_files {}
set fh [open $rocket_filelist r]
while {[gets $fh line] >= 0} {
set line [string trim $line]
if {$line eq ""} {
continue
}
set line [regsub {^\./} $line ""]
lappend rocket_files [file normalize [file join $rocket_rtl_dir $line]]
}
close $fh
puts "Reading Rocket Chip RTL..."
read_verilog -sv $rocket_files
read_verilog [file join $hardware_dir upstream rocket-chip src main resources vsrc plusarg_reader.v]
set gps_filelist [file join $hardware_dir external gps rtl filelist.f]
set gps_files {}
set gps_fh [open $gps_filelist r]
while {[gets $gps_fh rel] >= 0} {
set rel [string trim $rel]
if {$rel eq "" || [string match "#*" $rel]} {
continue
}
lappend gps_files [file join $gps_system_dir $rel]
}
close $gps_fh
puts "Reading GPS APB wrapper RTL from $gps_system_dir..."
set_property include_dirs [list [file join $gps_system_dir trck_src pulp_fifo]] [current_fileset]
read_verilog -sv $gps_files
puts "Reading VCU118 shell RTL..."
set shell_files [list \
[file join $hardware_dir ip max2771_spi rtl max2771_spi_engine.sv] \
[file join $hardware_dir fpga vcu118 rtl axi4_ram_64.sv] \
[file join $hardware_dir fpga vcu118 rtl axi4_slave_tieoff_64.sv] \
[file join $hardware_dir fpga vcu118 rtl rocket_bscan_dmi_tunnel.sv] \
]
if {$rf_input_mode eq "ethernet"} {
puts "Generating VCU118 Ethernet PCS/PMA IP..."
set ip_cache_dir [file join $repo_dir .gen sources_1 ip]
foreach old_ip [glob -nocomplain -directory $ip_cache_dir gig_ethernet_pcs_pma_0*] {
file delete -force $old_ip
}
source [file join $hardware_dir fpga vcu118 ip gig_ethernet_pcs_pma_0_vcu118.tcl]
generate_target all [get_ips gig_ethernet_pcs_pma_0]
synth_ip [get_ips gig_ethernet_pcs_pma_0]
foreach file [lsort [collect_sv_files [file join $hardware_dir fpga vcu118 rtl ethernet_rf]]] {
lappend shell_files $file
}
} else {
puts "Skipping VCU118 Ethernet RF IP/RTL for RF_INPUT_MODE=$rf_input_mode."
}
read_verilog -sv $shell_files
read_verilog -sv $wrapper
puts "Reading constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_rocket.xdc]
puts "Reading VCU118 PMOD SPI constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_pmod_spi.xdc]
puts "Reading VCU118 MAX2771 SPI constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_max2771_spi.xdc]
puts "Reading VCU118 PMOD sensor IRQ constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_pmod_irq.xdc]
puts "Reading VCU118 PMOD PPS constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_pmod_pps.xdc]
if {$rf_input_mode eq "pmod"} {
puts "Reading VCU118 PMOD RF constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_pmod_rf.xdc]
} elseif {$rf_input_mode eq "ethernet"} {
puts "Reading VCU118 Ethernet PHY constraints..."
read_xdc [file join $hardware_dir fpga vcu118 constraints vcu118_ethernet.xdc]
}
puts "Running synthesis for $part_name..."
synth_design -top $top_module -part $part_name -verilog_define SYNTHESIS
relax_vcu118_pmod_rf_clock_route $rf_input_mode
apply_vcu118_async_clock_groups
write_checkpoint -force [file join $checkpoint_dir post_synth.dcp]
report_utilization -hierarchical -file [file join $report_dir synth_utilization_hier.rpt]
report_utilization -file [file join $report_dir synth_utilization.rpt]
report_timing_summary -file [file join $report_dir synth_timing_summary.rpt]
puts "Running implementation..."
opt_design
write_checkpoint -force [file join $checkpoint_dir post_opt.dcp]
place_design
write_checkpoint -force [file join $checkpoint_dir post_place.dcp]
phys_opt_design -directive AggressiveExplore
write_checkpoint -force [file join $checkpoint_dir post_phys_opt.dcp]
route_design
write_checkpoint -force [file join $checkpoint_dir post_route.dcp]
report_utilization -file [file join $report_dir route_utilization.rpt]
report_timing_summary -file [file join $report_dir route_timing_summary.rpt]
report_drc -file [file join $report_dir route_drc.rpt]
report_power -file [file join $report_dir route_power.rpt]
set bit_file [file join $bit_dir vcu118_rocket.bit]
puts "Writing bitstream: $bit_file"
write_bitstream -force $bit_file
puts "VCU118 non-project flow complete."