diff options
Diffstat (limited to 'fpga/usrp3/tools/scripts/viv_utils.tcl')
-rw-r--r-- | fpga/usrp3/tools/scripts/viv_utils.tcl | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/fpga/usrp3/tools/scripts/viv_utils.tcl b/fpga/usrp3/tools/scripts/viv_utils.tcl new file mode 100644 index 000000000..32c67e874 --- /dev/null +++ b/fpga/usrp3/tools/scripts/viv_utils.tcl @@ -0,0 +1,290 @@ +# +# Copyright 2014-2015 Ettus Research +# + +# --------------------------------------------------- +# Create namespace and initialize global parameters +# --------------------------------------------------- +namespace eval ::vivado_utils { + # Export commands + namespace export \ + initialize_project \ + synthesize_design \ + check_design \ + generate_post_synth_reports \ + generate_post_place_reports \ + generate_post_route_reports \ + write_implementation_outputs \ + get_top_module \ + get_part_name \ + get_vivado_mode + + # Required environment variables + variable g_tools_dir $::env(VIV_TOOLS_DIR) + variable g_top_module $::env(VIV_TOP_MODULE) + variable g_part_name $::env(VIV_PART_NAME) + variable g_output_dir $::env(VIV_OUTPUT_DIR) + variable g_source_files $::env(VIV_DESIGN_SRCS) + variable g_vivado_mode $::env(VIV_MODE) + + # Optional environment variables + variable g_verilog_defs "" + if { [info exists ::env(VIV_VERILOG_DEFS) ] } { + set g_verilog_defs $::env(VIV_VERILOG_DEFS) + } + variable g_include_dirs "" + if { [info exists ::env(VIV_INCLUDE_DIRS) ] } { + set g_include_dirs $::env(VIV_INCLUDE_DIRS) + } +} + +# --------------------------------------------------- +# Create a new project in memory and add source files +# --------------------------------------------------- +proc ::vivado_utils::initialize_project { {save_to_disk 0} } { + variable g_top_module + variable g_part_name + variable g_output_dir + variable g_source_files + + variable bd_files "" + + file delete -force $g_output_dir/build.rpt + + if {$save_to_disk == 1} { + puts "BUILDER: Creating Vivado project ${g_top_module}_project.xpr for part $g_part_name" + create_project -part $g_part_name ${g_top_module}_project + } else { + puts "BUILDER: Creating Vivado project in memory for part $g_part_name" + create_project -in_memory -part $g_part_name + } + + foreach src_file $g_source_files { + set src_ext [file extension $src_file ] + if [expr [lsearch {.vhd .vhdl} $src_ext] >= 0] { + puts "BUILDER: Adding VHDL : $src_file" + read_vhdl -library work $src_file + } elseif [expr [lsearch {.v .vh .sv .svh} $src_ext] >= 0] { + puts "BUILDER: Adding Verilog : $src_file" + read_verilog $src_file + } elseif [expr [lsearch {.xdc} $src_ext] >= 0] { + puts "BUILDER: Adding XDC : $src_file" + read_xdc $src_file + } elseif [expr [lsearch {.xci} $src_ext] >= 0] { + puts "BUILDER: Adding IP : $src_file" + read_ip $src_file + set_property generate_synth_checkpoint true [get_files $src_file] + } elseif [expr [lsearch {.ngc .edif .edf} $src_ext] >= 0] { + puts "BUILDER: Adding Netlist : $src_file" + read_edif $src_file + } elseif [expr [lsearch {.bd} $src_ext] >= 0] { + puts "BUILDER: Adding Block Design to list (added after IP regeneration): $src_file" + append bd_files "$src_file " + } elseif [expr [lsearch {.bxml} $src_ext] >= 0] { + puts "BUILDER: Adding Block Design XML to list (added after IP regeneration): $src_file" + append bd_files "$src_file " + } elseif [expr [lsearch {.dat} $src_ext] >= 0] { + puts "BUILDER: Adding Data File : $src_file" + add_files $src_file + } else { + puts "BUILDER: \[WARNING\] File ignored!!!: $src_file" + } + } + + # The 'synth_ip [get_ips *]' step causes builds in Windows to recompile various + # pieces of the IP. This is time-consuming and unnecessary behavior, thus is removed. + # These steps are redundant anyway since the IP builder performs both of them. + # puts "BUILDER: Refreshing IP" + # generate_target all [get_ips *] + # synth_ip [get_ips *] + + #might seem silly, but we need to add the bd files after the ip regeneration. + foreach file $bd_files { + puts "BUILDER: Adding file from Block Design list: $file" + add_files -norecurse $file + } + + puts "BUILDER: Setting $g_top_module as the top module" + set_property top $g_top_module [current_fileset] +} + +# --------------------------------------------------- +# Synthesize design (Shortcut for Vivado's synth_design) +# --------------------------------------------------- +proc ::vivado_utils::synthesize_design {args} { + variable g_top_module + variable g_part_name + variable g_verilog_defs + variable g_include_dirs + + set vdef_args "" + foreach vdef $g_verilog_defs { + set vdef_args [concat $vdef_args "-verilog_define $vdef"] + } + set incdir_args "" + if { [string compare $g_include_dirs ""] != 0 } { + set incdir_args "-include_dirs $g_include_dirs" + } + + set synth_cmd "synth_design -top $g_top_module -part $g_part_name" + set synth_cmd [concat $synth_cmd $vdef_args] + set synth_cmd [concat $synth_cmd $incdir_args] + set synth_cmd [concat $synth_cmd $args] + puts "BUILDER: Synthesizing design" + eval $synth_cmd +} + +# --------------------------------------------------- +# Check design (Shortcut for Vivado's synth_design -rtl) +# --------------------------------------------------- +proc ::vivado_utils::check_design {args} { + variable g_top_module + variable g_part_name + variable g_verilog_defs + variable g_include_dirs + + set vdef_args "" + foreach vdef $g_verilog_defs { + set vdef_args [concat $vdef_args "-verilog_define $vdef"] + } + set incdir_args "" + if { [string compare $g_include_dirs ""] != 0 } { + set incdir_args "-include_dirs $g_include_dirs" + } + + set synth_cmd "synth_design -top $g_top_module -part $g_part_name -rtl -rtl_skip_ip -rtl_skip_constraints" + set synth_cmd [concat $synth_cmd $vdef_args] + set synth_cmd [concat $synth_cmd $incdir_args] + set synth_cmd [concat $synth_cmd $args] + puts "BUILDER: Checking syntax and elaborating design" + eval $synth_cmd +} + +# --------------------------------------------------- +# Generate post synthesis reports and checkpoint +# --------------------------------------------------- +proc ::vivado_utils::generate_post_synth_reports {} { + variable g_output_dir + + puts "BUILDER: Writing post-synthesis checkpoint" + write_checkpoint -force $g_output_dir/post_synth + puts "BUILDER: Writing post-synthesis reports" + report_utilization -file $g_output_dir/post_synth_util.rpt + report_utilization -hierarchical -file $g_output_dir/post_synth_util_hier.rpt + report_drc -ruledeck methodology_checks -file $g_output_dir/methodology.rpt + report_high_fanout_nets -file $g_output_dir/high_fanout_nets.rpt +} + +# --------------------------------------------------- +# Generate post placement reports and checkpoint +# --------------------------------------------------- +proc ::vivado_utils::generate_post_place_reports {} { + variable g_output_dir + + puts "BUILDER: Writing post-placement checkpoint" + write_checkpoint -force $g_output_dir/post_place + puts "BUILDER: Writing post-placement reports" + report_clock_utilization -file $g_output_dir/clock_util.rpt + report_utilization -file $g_output_dir/post_place_util.rpt + report_utilization -hierarchical -file $g_output_dir/post_place_util_hier.rpt + report_timing -sort_by group -max_paths 5 -path_type summary -file $g_output_dir/post_place_timing.rpt +} + +# --------------------------------------------------- +# Generate post route reports and checkpoint +# --------------------------------------------------- +proc ::vivado_utils::generate_post_route_reports {} { + variable g_output_dir + + puts "BUILDER: Writing post-route checkpoint" + write_checkpoint -force $g_output_dir/post_route + puts "BUILDER: Writing post-route reports" + if {[file exists "$g_output_dir/clock_util.rpt"] == 0} { + report_clock_utilization -file $g_output_dir/clock_util.rpt + } + report_timing_summary -file $g_output_dir/post_route_timing_summary.rpt + report_utilization -file $g_output_dir/post_route_util.rpt + report_utilization -hierarchical -file $g_output_dir/post_route_util_hier.rpt + report_power -file $g_output_dir/post_route_power.rpt + report_drc -file $g_output_dir/post_imp_drc.rpt + report_timing -sort_by group -max_paths 10 -path_type summary -file $g_output_dir/post_route_timing.rpt +} + +# --------------------------------------------------- +# Export implementation +# --------------------------------------------------- +proc ::vivado_utils::write_implementation_outputs { {byte_swap_bin 0} } { + variable g_output_dir + variable g_top_module + variable g_tools_dir + + puts "BUILDER: Writing implementation netlist and XDC" + write_verilog -force $g_output_dir/${g_top_module}_impl_netlist.v + write_xdc -no_fixed_only -force $g_output_dir/${g_top_module}_impl.xdc + puts "BUILDER: Writing bitfile" + write_bitstream -force $g_output_dir/${g_top_module}.bit + puts "BUILDER: Writing config bitstream" + set binsize [expr [file size $g_output_dir/${g_top_module}.bit]/(1024*1024)] + set binsize_pow2 [expr {int(pow(2,ceil(log($binsize)/log(2))))}] + set bin_iface [expr $byte_swap_bin?"SMAPx32":"SMAPx8"] + write_cfgmem -force -quiet -interface $bin_iface -format BIN -size $binsize_pow2 -disablebitswap -loadbit "up 0x0 $g_output_dir/${g_top_module}.bit" $g_output_dir/${g_top_module}.bin + puts "BUILDER: Writing debug probes" + write_debug_probes -force $g_output_dir/${g_top_module}.ltx + puts "BUILDER: Writing export report" + report_utilization -omit_locs -file $g_output_dir/build.rpt + report_timing_summary -no_detailed_paths -file $g_output_dir/build.rpt -append + if {! [string match -nocase {*timing constraints are met*} [read [open $g_output_dir/build.rpt]]]} { + send_msg_id {Builder 0-0} error "The design did not satisfy timing constraints. (Implementation outputs were still generated)" + } +} + +proc ::vivado_utils::write_netlist_outputs { {suffix ""} } { + variable g_output_dir + variable g_top_module + + puts "BUILDER: Writing EDIF netlist and XDC" + set filename ${g_output_dir}/${g_top_module} + if { [expr [string length $suffix] > 0] } { + set filename ${filename}_${suffix} + } + write_edif -force ${filename}.edf + write_xdc -no_fixed_only -force ${filename}.xdc + puts "BUILDER: Writing export report" + report_utilization -omit_locs -file $g_output_dir/build.rpt + report_timing_summary -no_detailed_paths -file $g_output_dir/build.rpt -append + if {! [string match -nocase {*timing constraints are met*} [read [open $g_output_dir/build.rpt]]]} { + send_msg_id {Builder 0-0} error "The design did not meet all timing constraints. (Implementation outputs were still generated)" + } +} + +# --------------------------------------------------- +# Close project +# --------------------------------------------------- +proc ::vivado_utils::close_batch_project {} { + variable g_vivado_mode + + if [string equal $g_vivado_mode "batch"] { + puts "BUILDER: Closing project" + close_project + } else { + puts "BUILDER: In GUI mode. Leaving project open." + } +} + +# --------------------------------------------------- +# Get state variables +# --------------------------------------------------- +proc ::vivado_utils::get_top_module {} { + variable g_top_module + return $g_top_module +} + +proc ::vivado_utils::get_part_name {} { + variable g_part_name + return $g_part_name +} + +proc ::vivado_utils::get_vivado_mode {} { + variable g_vivado_mode + return $g_vivado_mode +} |