使用 Vivado 并行编程多个器件
Programming multiple devices parallelly using Vivado
我们有一个设置,其中两个 Xilinx FPGA 设备分别连接到计算机。我们使用 Vivado Tcl 控制台在我们的自动化环境中对 FPGA 进行编程。我能够成功地一个接一个地对两个设备进行编程。但是,我试图通过并行启动两个 vivado 实例并同时对每个设备进行编程来减少编程时间。这样做时,出现如下错误:
Targets(s) ", jsn-JTAG-SMT2-XXXXXXXXjsn-JTAG-HS3-XXXXXXXX" may be locked by another hw_server.
Error Message: ERROR: [Common 17-39] 'get_hw_targets' failed due to earlier errors.
这是我的 python 脚本,它在不同端口上启动 hw_server 和 cs_server 并并行编程 FPGA。
def program(hw_server_cmd, cs_server_cmd, cmd):
cs_server_process = subprocess.Popen(cs_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
cs_server_process.wait()
print("cs_server started")
hw_server_process = subprocess.Popen(hw_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
hw_server_process.wait()
print("hw_server started")
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
p.wait()
stdout, stderr = p.communicate()
p.wait()
hw_server_process.kill()
cs_server_process.kill()
print('Command [{}] return value: {}'.format(cmd, p.returncode))
print('stdout for cmd [{}]: {}'.format(cmd, stdout))
print('stderr for cmd [{}]: {}'.format(cmd, stderr))
if __name__ == '__main__':
cs_server_cmd_1 = r"C:\Xilinx\Vivado20.1\bin\cs_server.bat -d -stcp::3041"
hw_server_cmd_1 = r"C:\Xilinx\Vivado20.1\bin\hw_server.bat -d -stcp::3121"
cmd_1 = r'C:\Xilinx\Vivado20.1\bin\vivado.bat -mode tcl -source ProgFPGA_1.tcl'
cs_server_cmd_2 = r"C:\Xilinx\Vivado20.1\bin\cs_server.bat -d -stcp::3042"
hw_server_cmd_2 = r"C:\Xilinx\Vivado20.1\bin\hw_server.bat -d -stcp::3122"
cmd_2 = r'C:\Xilinx\Vivado20.1\bin\vivado.bat -mode tcl -source ProgFPGA_2.tcl'
fpga_prog_threads = {}
fpga_prog_threads[0] = threading.Thread(name=f'Programming FPGA on Platform 1', target=program, args=[hw_server_cmd_1, cs_server_cmd_1, cmd_1])
fpga_prog_threads[1] = threading.Thread(name=f'Programming FPGA on Platform 2', target=program, args=[hw_server_cmd_2, cs_server_cmd_2, cmd_2])
for t in fpga_prog_threads.values():
t.start()
#t.join()
join_all_threads(list(fpga_prog_threads.values()), 3600)
这是我使用的 tcl 脚本之一。另一个文件也包含相同的命令集,但端口号和序列号不同。
open_hw_manager
connect_hw_server -url 127.0.0.1:3121 -cs_url 127.0.0.1:3041 -allow_non_jtag
current_hw_server 127.0.0.1:3121
current_hw_target [get_hw_targets */xilinx_tcf/Digilent/XXXXXXXXXX]
open_hw_target
current_hw_device [lindex [get_hw_devices] 0]
refresh_hw_device -update_hw_probes false [lindex [get_hw_devices] 0]
set_property PROBES.FILE {} [lindex [get_hw_devices] 0]
set_property FULL_PROBES.FILE {} [lindex [get_hw_devices] 0]
set_property PROGRAM.FILE {C:/temp/bitfile2.bit} [lindex [get_hw_devices] 0]
program_hw_devices [lindex [get_hw_devices] 0]
refresh_hw_device [lindex [get_hw_devices] 0]
exit
有人可以指出我在这里做错了什么阻止我同时对设备进行编程吗?
P.S:最初我们使用Xilinx ISE。我尝试使用 impact.exe 同时对设备进行编程。在那种情况下,一个 FPGA 或另一个总是返回错误消息,如“Pin 没有变高”。
我想知道每个设备是否有 1 根 JTAG 电缆。如果这样做,则可以为每根电缆启动一个 hw_server 实例。有关如何执行此操作的详细信息,请参见此处:
在您的情况下,可以启动一个 hw_server 个实例,例如:
hw_server -stcp::3122 -e "set jtag-port-filter Digilent/xxx"
将 xxx 值替换为电缆中的相应 ID。
请注意,对于 windows,我不确定引号是否有效。所以在这种情况下,您可能需要使用传入 hw_server.
的初始化文件
使用这个例子,初始化文本文件看起来像这样:
# set JTAG port filter
set jtag-port-filter Digilent/xxx
假设您调用文件 'cable1.init' 然后您可以按如下方式启动服务器:
hw_server -stcp::3122 --init=cable1.init
第二个实例与此设置类似,但您将使用 stcp 选项和电缆配置指定不同的端口以指向第二根电缆。
编程时,您将使用端口号与设备通信,现在您应该可以并行编程了。
我们有一个设置,其中两个 Xilinx FPGA 设备分别连接到计算机。我们使用 Vivado Tcl 控制台在我们的自动化环境中对 FPGA 进行编程。我能够成功地一个接一个地对两个设备进行编程。但是,我试图通过并行启动两个 vivado 实例并同时对每个设备进行编程来减少编程时间。这样做时,出现如下错误:
Targets(s) ", jsn-JTAG-SMT2-XXXXXXXXjsn-JTAG-HS3-XXXXXXXX" may be locked by another hw_server.
Error Message: ERROR: [Common 17-39] 'get_hw_targets' failed due to earlier errors.
这是我的 python 脚本,它在不同端口上启动 hw_server 和 cs_server 并并行编程 FPGA。
def program(hw_server_cmd, cs_server_cmd, cmd):
cs_server_process = subprocess.Popen(cs_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
cs_server_process.wait()
print("cs_server started")
hw_server_process = subprocess.Popen(hw_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
hw_server_process.wait()
print("hw_server started")
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
p.wait()
stdout, stderr = p.communicate()
p.wait()
hw_server_process.kill()
cs_server_process.kill()
print('Command [{}] return value: {}'.format(cmd, p.returncode))
print('stdout for cmd [{}]: {}'.format(cmd, stdout))
print('stderr for cmd [{}]: {}'.format(cmd, stderr))
if __name__ == '__main__':
cs_server_cmd_1 = r"C:\Xilinx\Vivado20.1\bin\cs_server.bat -d -stcp::3041"
hw_server_cmd_1 = r"C:\Xilinx\Vivado20.1\bin\hw_server.bat -d -stcp::3121"
cmd_1 = r'C:\Xilinx\Vivado20.1\bin\vivado.bat -mode tcl -source ProgFPGA_1.tcl'
cs_server_cmd_2 = r"C:\Xilinx\Vivado20.1\bin\cs_server.bat -d -stcp::3042"
hw_server_cmd_2 = r"C:\Xilinx\Vivado20.1\bin\hw_server.bat -d -stcp::3122"
cmd_2 = r'C:\Xilinx\Vivado20.1\bin\vivado.bat -mode tcl -source ProgFPGA_2.tcl'
fpga_prog_threads = {}
fpga_prog_threads[0] = threading.Thread(name=f'Programming FPGA on Platform 1', target=program, args=[hw_server_cmd_1, cs_server_cmd_1, cmd_1])
fpga_prog_threads[1] = threading.Thread(name=f'Programming FPGA on Platform 2', target=program, args=[hw_server_cmd_2, cs_server_cmd_2, cmd_2])
for t in fpga_prog_threads.values():
t.start()
#t.join()
join_all_threads(list(fpga_prog_threads.values()), 3600)
这是我使用的 tcl 脚本之一。另一个文件也包含相同的命令集,但端口号和序列号不同。
open_hw_manager
connect_hw_server -url 127.0.0.1:3121 -cs_url 127.0.0.1:3041 -allow_non_jtag
current_hw_server 127.0.0.1:3121
current_hw_target [get_hw_targets */xilinx_tcf/Digilent/XXXXXXXXXX]
open_hw_target
current_hw_device [lindex [get_hw_devices] 0]
refresh_hw_device -update_hw_probes false [lindex [get_hw_devices] 0]
set_property PROBES.FILE {} [lindex [get_hw_devices] 0]
set_property FULL_PROBES.FILE {} [lindex [get_hw_devices] 0]
set_property PROGRAM.FILE {C:/temp/bitfile2.bit} [lindex [get_hw_devices] 0]
program_hw_devices [lindex [get_hw_devices] 0]
refresh_hw_device [lindex [get_hw_devices] 0]
exit
有人可以指出我在这里做错了什么阻止我同时对设备进行编程吗?
P.S:最初我们使用Xilinx ISE。我尝试使用 impact.exe 同时对设备进行编程。在那种情况下,一个 FPGA 或另一个总是返回错误消息,如“Pin 没有变高”。
我想知道每个设备是否有 1 根 JTAG 电缆。如果这样做,则可以为每根电缆启动一个 hw_server 实例。有关如何执行此操作的详细信息,请参见此处:
在您的情况下,可以启动一个 hw_server 个实例,例如:
hw_server -stcp::3122 -e "set jtag-port-filter Digilent/xxx"
将 xxx 值替换为电缆中的相应 ID。
请注意,对于 windows,我不确定引号是否有效。所以在这种情况下,您可能需要使用传入 hw_server.
的初始化文件使用这个例子,初始化文本文件看起来像这样:
# set JTAG port filter
set jtag-port-filter Digilent/xxx
假设您调用文件 'cable1.init' 然后您可以按如下方式启动服务器:
hw_server -stcp::3122 --init=cable1.init
第二个实例与此设置类似,但您将使用 stcp 选项和电缆配置指定不同的端口以指向第二根电缆。
编程时,您将使用端口号与设备通信,现在您应该可以并行编程了。