232 lines
8.4 KiB
Tcl
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."
|