Skip to content

Commit

Permalink
feat[vivado]: fix for #426
Browse files Browse the repository at this point in the history
This commit updates tools/vivado.py to allow the user to skip the
link_design step normally used after reading in a toplevel netlist.

The use case here is when an EDIF netlist, or any other netlist, is read
in as a submodule and is not the toplevel.  In this case the link_design
step will fail as Vivado is expecting a netlist with the toplevel name.

In order to bypass the link_design step, use the no_link_design tag when
specifying the netlist in your Core file:

filesets:
  netlist:
    files:
      - cute_a7_core/cute_a7_core.edf: { file_type: edif, tags: [no_link_design] }
  • Loading branch information
shareefj authored and olofk committed Nov 11, 2024
1 parent c07de87 commit 683c7b6
Show file tree
Hide file tree
Showing 14 changed files with 447 additions and 1 deletion.
5 changes: 4 additions & 1 deletion edalize/tools/vivado.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def setup(self, edam):
has_xci = False
unused_files = []
bd_files = []
netlist_flow = False

dep_files = []
for f in self.files:
Expand All @@ -119,6 +120,8 @@ def setup(self, edam):
elif file_type == "edif":
cmd = "read_edif"
edif_files.append(f["name"])
if not "no_link_design" in f.get("tags", []):
netlist_flow = True
elif file_type.startswith("vhdlSource"):
cmd = "read_vhdl"
if file_type == "vhdlSource-2008":
Expand Down Expand Up @@ -176,7 +179,7 @@ def setup(self, edam):
"vlogparam": self.vlogparam,
"vlogdefine": self.vlogdefine,
"generic": self.generic,
"netlist_flow": bool(edif_files),
"netlist_flow": netlist_flow,
"has_vhdl2008": has_vhdl2008,
"has_xci": has_xci,
"bd_files": bd_files,
Expand Down
48 changes: 48 additions & 0 deletions tests/test_vivado.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,51 @@ def test_vivado_board_file(make_edalize_test):

tf.backend.build()
tf.compare_files(["vivado.cmd"])


def test_vivado_edif_netlist(make_edalize_test):
tf = make_edalize_test(
"vivado",
ref_dir="edif_netlist",
files=[{"name": "netlist.edif", "file_type": "edif"}],
param_types=["generic", "vlogdefine", "vlogparam"],
tool_options={"part": "xc7a35tcsg324-1"},
)
tf.backend.configure()
tf.compare_files(
[
"Makefile",
tf.test_name + ".tcl",
tf.test_name + "_synth.tcl",
tf.test_name + "_run.tcl",
tf.test_name + "_pgm.tcl",
]
)

tf.backend.build()
tf.compare_files(["vivado.cmd"])


def test_vivado_edif_netlist_no_link_design(make_edalize_test):
tf = make_edalize_test(
"vivado",
ref_dir="edif_netlist_no_link_design",
files=[
{"name": "netlist.edif", "file_type": "edif", "tags": ["no_link_design"]}
],
param_types=["generic", "vlogdefine", "vlogparam"],
tool_options={"part": "xc7a35tcsg324-1"},
)
tf.backend.configure()
tf.compare_files(
[
"Makefile",
tf.test_name + ".tcl",
tf.test_name + "_synth.tcl",
tf.test_name + "_run.tcl",
tf.test_name + "_pgm.tcl",
]
)

tf.backend.build()
tf.compare_files(["vivado.cmd"])
30 changes: 30 additions & 0 deletions tests/test_vivado/edif_netlist/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#Auto generated by Edalize

all: post_build

pre_build:

test_vivado_0.xpr: test_vivado_0.tcl netlist.edif netlist.edif | pre_build
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0.tcl

test_vivado_0.v test_vivado_0.edn: test_vivado_0_synth.tcl test_vivado_0_netlist.tcl | test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0_synth.tcl test_vivado_0_netlist.tcl test_vivado_0.xpr

synth: test_vivado_0.v test_vivado_0.edn

test_vivado_0.bit: test_vivado_0_synth.tcl test_vivado_0_run.tcl | test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0_synth.tcl test_vivado_0_run.tcl test_vivado_0.xpr

build-gui: test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado test_vivado_0.xpr

pgm: test_vivado_0_pgm.tcl test_vivado_0.bit
$(EDALIZE_LAUNCHER) vivado -quiet -nolog -notrace -mode batch -source test_vivado_0_pgm.tcl -tclargs xc7a35tcsg324-1 test_vivado_0.bit

post_build: test_vivado_0.bit

pre_run:

run: pre_run

post_run: run
19 changes: 19 additions & 0 deletions tests/test_vivado/edif_netlist/test_vivado_0.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Auto-generated project tcl file


create_project test_vivado_0 -force

set_property part xc7a35tcsg324-1 [current_project]


set_property generic {vlogparam_bool=1 vlogparam_int=42 vlogparam_str=hello } [get_filesets sources_1]
set_property generic {generic_bool=true generic_int=42 generic_str=hello } [get_filesets sources_1]
set_property verilog_define {vlogdefine_bool=1 vlogdefine_int=42 vlogdefine_str=hello } [get_filesets sources_1]
read_edif {netlist.edif}

set_property include_dirs [list .] [get_filesets sources_1]
set_property top top_module [current_fileset]
set_property source_mgmt_mode None [current_project]


link_design -top test_vivado_0 -part xc7a35tcsg324-1
105 changes: 105 additions & 0 deletions tests/test_vivado/edif_netlist/test_vivado_0_pgm.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Auto-generated program tcl file

set part [lindex $argv 0]
set bitstream [lindex $argv 1]


if {[info exists env(HW_TARGET)]} {
set explicit_hw_target $env(HW_TARGET)
} else {
set explicit_hw_target ""
}
if {[info exists env(JTAG_FREQ)]} {
set jtag_freq $env(JTAG_FREQ)
} else {
set jtag_freq ""
}

puts "FuseSoC Xilinx FPGA Programming Tool"
puts "===================================="
puts ""
puts "INFO: Programming part $part with bitstream $bitstream"
if { $explicit_hw_target != "" } {
puts "INFO: Programming target $explicit_hw_target"
}

# Connect to Xilinx Hardware Server
if { [ catch { open_hw_manager } ] } { open_hw }
connect_hw_server

if { $explicit_hw_target == "" } {
set hw_targets [get_hw_targets]
} else {
set hw_targets [get_hw_targets $explicit_hw_target]
}

if { [llength $hw_targets] == 0 } {
if { $explicit_hw_target == "" } {
puts "ERROR: Failed to find any targets"
} else {
puts "ERROR: Failed to find target: $target"
}
}

# Find the first target and device that contains a FPGA $part.
set hw_device_found 0
foreach hw_target $hw_targets {
puts "INFO: Trying to use hardware target $hw_target"
current_hw_target $hw_target

# Open hardware target
# The Vivado hardware server isn't always able to reliably open a target.
# Try three times before giving up.
set hw_target_opened 0
for {set open_hw_target_try 1} {$open_hw_target_try <= 3} {incr open_hw_target_try} {
if {[catch {open_hw_target} res_open_hw_target] == 0} {
set hw_target_opened 1
break
}
}
if { $hw_target_opened == 0 } {
puts "WARNING: Unable to open hardware target $hw_target after " \
"$open_hw_target_try tries. Skipping."
continue
}
puts "INFO: Opened hardware target $hw_target on try $open_hw_target_try."

# Iterate through all devices and find one which contains $part
foreach { hw_device } [get_hw_devices] {
if { [string first [get_property PART $hw_device] $part] == 0 } {
puts "INFO: Found $part as part of $hw_device."
current_hw_device $hw_device
set hw_device_found 1
break
}
}

if { $hw_device_found == 1 } {
break
} else {
# Close currently tried device, and try with next one.
puts "INFO: Part not found as part of $hw_target. Trying next device."
close_hw_target
}
}
if { $hw_device_found == 0 } {
puts "ERROR: None of the hardware targets included a $part FPGA part. \
Check cables and ensure that jumpers are correct for JTAG programming."
exit 1
}
puts "INFO: Programming bitstream to device $hw_device on target $hw_target."

# Do the programming
current_hw_device $hw_device
set_property PROGRAM.FILE $bitstream [current_hw_device]
if {$jtag_freq != ""} {
set_property PARAM.FREQUENCY $jtag_freq [get_hw_targets $hw_target]
}
program_hw_devices [current_hw_device]

# Disconnect from Xilinx Hardware Server
close_hw_target
disconnect_hw_server

puts ""
puts "INFO: SUCCESS! FPGA $part successfully programmed with bitstream $bitstream."
33 changes: 33 additions & 0 deletions tests/test_vivado/edif_netlist/test_vivado_0_run.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Create a bin file which can be used to program the flash on the FPGA
set_property STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE true [get_runs impl_1]

# Vivado will raise an error if impl_1 is launched when it is already done. So
# check the progress first and only launch if its not complete.
if { [get_property PROGRESS [get_runs impl_1]] != "100%"} {
# Vivado only outputs to stdout for jobs that are explicitly waited on with
# 'wait_on_run'. So launch and wait on synth then launch and wait on impl to
# get logging to stdout from both.

launch_runs impl_1 -to_step write_bitstream
wait_on_run impl_1
puts "Bitstream generation completed"
} else {
puts "Bitstream generation already complete"
}

if { [get_property PROGRESS [get_runs impl_1]] != "100%"} {
puts "ERROR: Implementation and bitstream generation step failed."
exit 1
}

# By default, Vivado writes the bitstream to a file named after the toplevel and
# put into the *.runs/impl_1 folder.
# fusesoc/edalize historically used a bitstream name based on the project name,
# and puts it into the top-level project workroot.
# To keep backwards-compat, copy the Vivado default bitstream file to the
# traditional edalize location.
# The Vivado default name is beneficial when using the GUI, as it is set as
# default bitstream in the "Program Device" dialog; non-standard names need to
# be selected from a file picker first.
set vivadoDefaultBitstreamFile [ get_property DIRECTORY [current_run] ]/[ get_property top [current_fileset] ].bit
file copy -force $vivadoDefaultBitstreamFile [pwd]/[current_project].bit
9 changes: 9 additions & 0 deletions tests/test_vivado/edif_netlist/test_vivado_0_synth.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
set outdated [get_property NEEDS_REFRESH [get_runs synth_1]]
set progress [get_property PROGRESS [get_runs synth_1]]

if {$outdated || $progress != "100%"} {
reset_runs synth_1
launch_runs synth_1
wait_on_run synth_1
}
#exit [regexp -nocase -- {synth_design (error|failed)} [get_property STATUS [get_runs synth_1]] match]
2 changes: 2 additions & 0 deletions tests/test_vivado/edif_netlist/vivado.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-notrace -mode batch -source test_vivado_0.tcl
-notrace -mode batch -source test_vivado_0_synth.tcl test_vivado_0_run.tcl test_vivado_0.xpr
30 changes: 30 additions & 0 deletions tests/test_vivado/edif_netlist_no_link_design/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#Auto generated by Edalize

all: post_build

pre_build:

test_vivado_0.xpr: test_vivado_0.tcl netlist.edif netlist.edif | pre_build
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0.tcl

test_vivado_0.v test_vivado_0.edn: test_vivado_0_synth.tcl test_vivado_0_netlist.tcl | test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0_synth.tcl test_vivado_0_netlist.tcl test_vivado_0.xpr

synth: test_vivado_0.v test_vivado_0.edn

test_vivado_0.bit: test_vivado_0_synth.tcl test_vivado_0_run.tcl | test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado -notrace -mode batch -source test_vivado_0_synth.tcl test_vivado_0_run.tcl test_vivado_0.xpr

build-gui: test_vivado_0.xpr
$(EDALIZE_LAUNCHER) vivado test_vivado_0.xpr

pgm: test_vivado_0_pgm.tcl test_vivado_0.bit
$(EDALIZE_LAUNCHER) vivado -quiet -nolog -notrace -mode batch -source test_vivado_0_pgm.tcl -tclargs xc7a35tcsg324-1 test_vivado_0.bit

post_build: test_vivado_0.bit

pre_run:

run: pre_run

post_run: run
18 changes: 18 additions & 0 deletions tests/test_vivado/edif_netlist_no_link_design/test_vivado_0.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Auto-generated project tcl file


create_project test_vivado_0 -force

set_property part xc7a35tcsg324-1 [current_project]


set_property generic {vlogparam_bool=1 vlogparam_int=42 vlogparam_str=hello } [get_filesets sources_1]
set_property generic {generic_bool=true generic_int=42 generic_str=hello } [get_filesets sources_1]
set_property verilog_define {vlogdefine_bool=1 vlogdefine_int=42 vlogdefine_str=hello } [get_filesets sources_1]
read_edif {netlist.edif}

set_property include_dirs [list .] [get_filesets sources_1]
set_property top top_module [current_fileset]
set_property source_mgmt_mode None [current_project]


Loading

0 comments on commit 683c7b6

Please sign in to comment.